public static void openFile(
		ServletContext servletContext,
		HttpServletRequest request,
		HttpServletResponse response,
		DomainName domain,
		Path book,
		final Path path
	) throws ServletException, IOException, SkipPageException {
		// Only allow from localhost and when open enabled
		if(!isAllowed(servletContext, request)) {
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			throw ServletUtil.SKIP_PAGE_EXCEPTION;
		} else {
			final String[] command;
			ResourceRef resourceRef = ResourceRefResolver.getResourceRef(servletContext, request, domain, book, path.toString());
			Book bookObj = SemanticCMS.getInstance(servletContext).getBook(resourceRef.getBookRef());
			if(bookObj.isAccessible()) throw new FileNotFoundException("Book is inaccessible: " + resourceRef);
			ResourceStore resourceStore = bookObj.getResources();
			if(!resourceStore.isAvailable()) throw new FileNotFoundException("Resource store is unavailable: " + resourceRef);
			java.io.File resourceFile = resourceStore.getResource(resourceRef.getPath()).getFile();
			if(resourceFile == null) throw new FileNotFoundException("Resource is not a local file: " + resourceRef);
			if(resourceFile.isDirectory()) {
				command = new String[] {
					// TODO: What is good windows path?
					//isWindows()
					//	? "C:\\Program Files (x86)\\OpenOffice 4\\program\\swriter.exe"
					"/usr/bin/konqueror",
					resourceFile.getCanonicalPath()
				};
			} else {
				// Open the file with the appropriate application based on extension
				String extension = FileUtils.getExtension(resourceFile.getName()).toLowerCase(Locale.ROOT);
				// Check registered file openers first
				FileOpener fileOpener;
				synchronized(fileOpenersLock) {
					@SuppressWarnings("unchecked")
					Map<String,FileOpener> fileOpeners = (Map<String,FileOpener>)servletContext.getAttribute(FILE_OPENERS_REQUEST_ATTRIBUTE_NAME);
					if(fileOpeners != null) {
						fileOpener = fileOpeners.get(extension);
					} else {
						fileOpener = null;
					}
				}
				if(fileOpener != null) {
					command = fileOpener.getCommand(resourceFile);
				} else {
					// Use default behavior
					switch(extension) {
						case "gif" :
						case "jpg" :
						case "jpeg" :
						case "png" :
							command = new String[] {
								isWindows()
									? "C:\\Program Files (x86)\\OpenOffice 4\\program\\swriter.exe"
									: "/usr/bin/gwenview",
								resourceFile.getCanonicalPath()
							};
							break;
						case "doc" :
						case "docx" :
						case "odt" :
							command = new String[] {
								isWindows()
									? "C:\\Program Files (x86)\\OpenOffice 4\\program\\swriter.exe"
									: "/usr/bin/libreoffice",
								"--writer",
								resourceFile.getCanonicalPath()
							};
							break;
						case "csv" :
						case "ods" :
						case "sxc" :
						case "xls" :
							command = new String[] {
								isWindows()
									? "C:\\Program Files (x86)\\OpenOffice 4\\program\\scalc.exe"
									: "/usr/bin/libreoffice",
								"--calc",
								resourceFile.getCanonicalPath()
							};
							break;
						case "pdf" :
							command = new String[] {
								isWindows()
									? "C:\\Program Files (x86)\\Adobe\\Reader 11.0\\Reader\\AcroRd32.exe"
									: "/usr/bin/okular",
								resourceFile.getCanonicalPath()
							};
							break;
						case "c" :
						case "csh" :
						case "h" :
						case "java" :
						case "jsp" :
						case "jspx" :
						case "sh" :
						case "txt" :
						case "xml" :
							if(isWindows()) {
								command = new String[] {
									"C:\\Program Files\\NetBeans 7.4\\bin\\netbeans64.exe",
									"--open",
									resourceFile.getCanonicalPath()
								};
							} else {
								command = new String[] {
									//"/usr/bin/kwrite",
									"/opt/netbeans-8.0.2/bin/netbeans",
									"--jdkhome",
									getJdkPath(),
									"--open",
									resourceFile.getCanonicalPath()
								};
							}
							break;
						case "dia" :
							command = new String[] {
								isWindows()
									? "C:\\Program Files (x86)\\Dia\\bin\\diaw.exe"
									: "/usr/bin/dia",
								resourceFile.getCanonicalPath()
							};
							break;
						case "zip" :
							if(isWindows()) {
								command = new String[] {
									resourceFile.getCanonicalPath()
								};
							} else {
								command = new String[] {
									"/usr/bin/konqueror",
									resourceFile.getCanonicalPath()
								};
							}
							break;
						case "mp3" :
						case "wma" :
							command = new String[] {
								isWindows()
									? "C:\\Program Files\\VideoLAN\\VLC.exe"
									: "/usr/bin/vlc",
								resourceFile.getCanonicalPath()
							};
							break;
						default :
							throw new IllegalArgumentException("Unsupprted file type by extension: " + extension);
					}
				}
			}
			// Start the process
			final Process process = Runtime.getRuntime().exec(command);
			// Result is watched in the background only
			// Java 1.8: Lambda
			new Thread(
				new Runnable() {
					@Override
					public void run() {
						try {
							final ProcessResult result = ProcessResult.getProcessResult(process);
							int exitVal = result.getExitVal();
							if(exitVal != 0) {
								logger.log(Level.SEVERE, "Non-zero exit status from \"{0}\": {1}", new Object[]{path, exitVal});
							}
							String stdErr = result.getStderr();
							if(!stdErr.isEmpty()) {
								logger.log(Level.SEVERE, "Standard error from \"{0}\":\n{1}", new Object[]{path, stdErr});
							}
							if(logger.isLoggable(Level.INFO)) {
								String stdOut = result.getStdout();
								if(!stdOut.isEmpty()) {
									logger.log(Level.INFO, "Standard output from \"{0}\":\n{1}", new Object[]{path, stdOut});
								}
							}
						} catch(IOException e) {
							logger.log(Level.SEVERE, null, e);
						}
					}
				}
			).start();
		}
	}
public static void openFile ( ServletContext servletContext , HttpServletRequest request , HttpServletResponse response , DomainName domain , Path book , final Path path ) throws ServletException , IOException , SkipPageException { if ( ! isAllowed ( servletContext , request ) ) { response . sendError ( HttpServletResponse . SC_FORBIDDEN ) ; throw ServletUtil . SKIP_PAGE_EXCEPTION ; } else { final String [ ] command ; ResourceRef resourceRef = ResourceRefResolver . getResourceRef ( servletContext , request , domain , book , path . toString ( ) ) ; Book bookObj = SemanticCMS . getInstance ( servletContext ) . getBook ( resourceRef . getBookRef ( ) ) ; if ( bookObj . isAccessible ( ) ) throw new FileNotFoundException ( "Book is inaccessible: " + resourceRef ) ; ResourceStore resourceStore = bookObj . getResources ( ) ; if ( ! resourceStore . isAvailable ( ) ) throw new FileNotFoundException ( "Resource store is unavailable: " + resourceRef ) ; java . io . File resourceFile = resourceStore . getResource ( resourceRef . getPath ( ) ) . getFile ( ) ; if ( resourceFile == null ) throw new FileNotFoundException ( "Resource is not a local file: " + resourceRef ) ; if ( resourceFile . isDirectory ( ) ) { command = new String [ ] { "/usr/bin/konqueror" , resourceFile . getCanonicalPath ( ) } ; } else { String extension = FileUtils . getExtension ( resourceFile . getName ( ) ) . toLowerCase ( Locale . ROOT ) ; FileOpener fileOpener ; synchronized ( fileOpenersLock ) { @ SuppressWarnings ( "unchecked" ) Map < String , FileOpener > fileOpeners = ( Map < String , FileOpener > ) servletContext . getAttribute ( FILE_OPENERS_REQUEST_ATTRIBUTE_NAME ) ; if ( fileOpeners != null ) { fileOpener = fileOpeners . get ( extension ) ; } else { fileOpener = null ; } } if ( fileOpener != null ) { command = fileOpener . getCommand ( resourceFile ) ; } else { switch ( extension ) { case "gif" : case "jpg" : case "jpeg" : case "png" : command = new String [ ] { isWindows ( ) ? "C:\\Program Files (x86)\\OpenOffice 4\\program\\swriter.exe" : "/usr/bin/gwenview" , resourceFile . getCanonicalPath ( ) } ; break ; case "doc" : case "docx" : case "odt" : command = new String [ ] { isWindows ( ) ? "C:\\Program Files (x86)\\OpenOffice 4\\program\\swriter.exe" : "/usr/bin/libreoffice" , "--writer" , resourceFile . getCanonicalPath ( ) } ; break ; case "csv" : case "ods" : case "sxc" : case "xls" : command = new String [ ] { isWindows ( ) ? "C:\\Program Files (x86)\\OpenOffice 4\\program\\scalc.exe" : "/usr/bin/libreoffice" , "--calc" , resourceFile . getCanonicalPath ( ) } ; break ; case "pdf" : command = new String [ ] { isWindows ( ) ? "C:\\Program Files (x86)\\Adobe\\Reader 11.0\\Reader\\AcroRd32.exe" : "/usr/bin/okular" , resourceFile . getCanonicalPath ( ) } ; break ; case "c" : case "csh" : case "h" : case "java" : case "jsp" : case "jspx" : case "sh" : case "txt" : case "xml" : if ( isWindows ( ) ) { command = new String [ ] { "C:\\Program Files\\NetBeans 7.4\\bin\\netbeans64.exe" , "--open" , resourceFile . getCanonicalPath ( ) } ; } else { command = new String [ ] { "/opt/netbeans-8.0.2/bin/netbeans" , "--jdkhome" , getJdkPath ( ) , "--open" , resourceFile . getCanonicalPath ( ) } ; } break ; case "dia" : command = new String [ ] { isWindows ( ) ? "C:\\Program Files (x86)\\Dia\\bin\\diaw.exe" : "/usr/bin/dia" , resourceFile . getCanonicalPath ( ) } ; break ; case "zip" : if ( isWindows ( ) ) { command = new String [ ] { resourceFile . getCanonicalPath ( ) } ; } else { command = new String [ ] { "/usr/bin/konqueror" , resourceFile . getCanonicalPath ( ) } ; } break ; case "mp3" : case "wma" : command = new String [ ] { isWindows ( ) ? "C:\\Program Files\\VideoLAN\\VLC.exe" : "/usr/bin/vlc" , resourceFile . getCanonicalPath ( ) } ; break ; default : throw new IllegalArgumentException ( "Unsupprted file type by extension: " + extension ) ; } } } final Process process = Runtime . getRuntime ( ) . exec ( command ) ; new Thread ( new Runnable ( ) { @ Override public void run ( ) { try { final ProcessResult result = ProcessResult . getProcessResult ( process ) ; int exitVal = result . getExitVal ( ) ; if ( exitVal != 0 ) { logger . log ( Level . SEVERE , "Non-zero exit status from \"{0}\": {1}" , new Object [ ] { path , exitVal } ) ; } String stdErr = result . getStderr ( ) ; if ( ! stdErr . isEmpty ( ) ) { logger . log ( Level . SEVERE , "Standard error from \"{0}\":\n{1}" , new Object [ ] { path , stdErr } ) ; } if ( logger . isLoggable ( Level . INFO ) ) { String stdOut = result . getStdout ( ) ; if ( ! stdOut . isEmpty ( ) ) { logger . log ( Level . INFO , "Standard output from \"{0}\":\n{1}" , new Object [ ] { path , stdOut } ) ; } } } catch ( IOException e ) { logger . log ( Level . SEVERE , null , e ) ; } } } ) . start ( ) ; } }
TODO: Should this only allow open of published books?