| Author | DaveJarvis <email> |
|---|---|
| Date | 2021-04-02 16:38:58 GMT-0700 |
| Commit | b6415a372a205b7a0706b4267fbd17c7ef4fe4ec |
| Parent | c41fc89 |
| +package com.keenwrite.io; | ||
| + | ||
| +import java.nio.file.Path; | ||
| +import java.nio.file.Paths; | ||
| +import java.util.stream.Stream; | ||
| + | ||
| +import static java.lang.System.getenv; | ||
| +import static java.nio.file.Files.isExecutable; | ||
| +import static java.util.regex.Pattern.quote; | ||
| + | ||
| +/** | ||
| + * Responsible for file-related functionality. | ||
| + */ | ||
| +public class File extends java.io.File { | ||
| + /** | ||
| + * For finding executable programs. | ||
| + */ | ||
| + private static final String[] EXTENSIONS = new String[] | ||
| + {"", ".com", ".exe", ".bat", ".cmd"}; | ||
| + | ||
| + /** | ||
| + * Creates a new instance for a given file name. | ||
| + * | ||
| + * @param pathname File name to represent for subsequent operations. | ||
| + */ | ||
| + public File( final String pathname ) { | ||
| + super( pathname ); | ||
| + } | ||
| + | ||
| + /** | ||
| + * For a file name that represents an executable (without an extension) | ||
| + * file, this determines whether the executable is found in the PATH | ||
| + * environment variable. This will search the PATH each time the method | ||
| + * is invoked, triggering a full directory scan for all paths listed in | ||
| + * the environment variable. The result is not cached, so avoid calling | ||
| + * this in a critical loop. | ||
| + * | ||
| + * @return {@code true} when the given file name references an executable | ||
| + * file located in the PATH environment variable. | ||
| + */ | ||
| + public boolean canExecute() { | ||
| + final var exe = getName(); | ||
| + final var paths = getenv( "PATH" ).split( quote( pathSeparator ) ); | ||
| + return Stream.of( paths ).map( Paths::get ).anyMatch( | ||
| + path -> { | ||
| + final var p = path.resolve( exe ); | ||
| + | ||
| + for( final var extension : EXTENSIONS ) { | ||
| + if( isExecutable( Path.of( p.toString() + extension ) ) ) { | ||
| + return true; | ||
| + } | ||
| + } | ||
| + | ||
| + return false; | ||
| + } | ||
| + ); | ||
| + } | ||
| +} | ||
| import java.io.File; | ||
| +import java.io.IOException; | ||
| import java.nio.file.Path; | ||
| import static com.keenwrite.io.MediaType.TypeName.*; | ||
| import static com.keenwrite.io.MediaTypeExtension.getMediaType; | ||
| +import static java.io.File.createTempFile; | ||
| import static org.apache.commons.io.FilenameUtils.getExtension; | ||
| public String getSubtype() { | ||
| return mSubtype; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Creates a temporary file for the given {@link MediaType}, which will be | ||
| + * deleted when the application exits. | ||
| + * | ||
| + * @param prefix The file name begins with this string (may be empty). | ||
| + * @return The fully qualified path to a file. | ||
| + * @throws IOException Could not create the temporary file. | ||
| + */ | ||
| + public Path createTemporaryFile( final String prefix ) throws IOException { | ||
| + final var file = createTempFile( | ||
| + prefix, '.' + MediaTypeExtension.valueFrom( this ).getExtension() ); | ||
| + file.deleteOnExit(); | ||
| + return file.toPath(); | ||
| } | ||
| import com.keenwrite.typesetting.Typesetter; | ||
| +import static com.keenwrite.Bootstrap.APP_TITLE_LOWERCASE; | ||
| import static com.keenwrite.events.StatusEvent.clue; | ||
| import static com.keenwrite.io.MediaType.TEXT_XML; | ||
| -import static com.keenwrite.util.FileUtils.createTemporaryFile; | ||
| import static java.nio.file.Files.writeString; | ||
| try { | ||
| final var sTypesetter = new Typesetter( mContext.getWorkspace() ); | ||
| - final var document = createTemporaryFile( TEXT_XML ); | ||
| + final var document = TEXT_XML.createTemporaryFile( APP_TITLE_LOWERCASE ); | ||
| final var exportPath = mContext.getExportPath(); | ||
| sTypesetter.typeset( writeString( document, xhtml ), exportPath ); | ||
| import com.keenwrite.io.MediaType; | ||
| import com.keenwrite.preferences.Workspace; | ||
| -import com.keenwrite.util.ProtocolScheme; | ||
| import java.io.FileNotFoundException; | ||
| import java.io.InputStream; | ||
| import java.net.URL; | ||
| import java.nio.file.Path; | ||
| import java.util.regex.Pattern; | ||
| +import static com.keenwrite.Bootstrap.APP_TITLE_LOWERCASE; | ||
| import static com.keenwrite.events.StatusEvent.clue; | ||
| import static com.keenwrite.io.MediaType.IMAGE_SVG_XML; | ||
| import static com.keenwrite.preferences.WorkspaceKeys.KEY_IMAGES_DIR; | ||
| import static com.keenwrite.preferences.WorkspaceKeys.KEY_IMAGES_ORDER; | ||
| -import static com.keenwrite.util.FileUtils.createTemporaryFile; | ||
| +import static com.keenwrite.util.ProtocolScheme.getProtocol; | ||
| import static java.lang.String.format; | ||
| import static java.nio.file.Files.copy; | ||
| InputStream svgIn; | ||
| - final var protocol = ProtocolScheme.getProtocol( src ); | ||
| + final var protocol = getProtocol( src ); | ||
| if( protocol.isRemote() ) { | ||
| if( mediaType != IMAGE_SVG_XML ) { | ||
| // Download into temporary directory. | ||
| - imageFile = createTemporaryFile( mediaType ); | ||
| + imageFile = mediaType.createTemporaryFile( APP_TITLE_LOWERCASE ); | ||
| copy( svgIn, imageFile, REPLACE_EXISTING ); | ||
| svgIn.close(); | ||
| package com.keenwrite.typesetting; | ||
| +import com.keenwrite.io.File; | ||
| import com.keenwrite.preferences.Key; | ||
| import com.keenwrite.preferences.Workspace; | ||
| import static com.keenwrite.preferences.WorkspaceKeys.KEY_TYPESET_CONTEXT_ENV; | ||
| import static com.keenwrite.preferences.WorkspaceKeys.KEY_TYPESET_CONTEXT_PATH; | ||
| -import static com.keenwrite.util.FileUtils.canExecute; | ||
| import static java.lang.String.format; | ||
| import static java.lang.System.currentTimeMillis; | ||
| */ | ||
| public class Typesetter { | ||
| - private static final String TYPESETTER = "context"; | ||
| + private static final File TYPESETTER = new File( "context"); | ||
| private static final ExecutorService sService = newFixedThreadPool( 5 ); | ||
| public void typeset( final Path input, final Path output ) | ||
| throws IOException { | ||
| - if( isInstalled() ) { | ||
| + if( TYPESETTER.canExecute() ) { | ||
| sService.submit( new TypesetTask( input, output ) ); | ||
| } | ||
| final var envs = getProperty( KEY_TYPESET_CONTEXT_ENV ); | ||
| - mArgs.add( TYPESETTER ); | ||
| + mArgs.add( TYPESETTER.getName() ); | ||
| mArgs.add( "--batchmode" ); | ||
| mArgs.add( "--purgeall" ); | ||
| private String getProperty( final Key key ) { | ||
| return mWorkspace.stringProperty( key ).get(); | ||
| - } | ||
| - | ||
| - /** | ||
| - * Helps ensure that the typesetting software can be run. | ||
| - * | ||
| - * @return {@code true} when the typesetting software is available. | ||
| - */ | ||
| - private boolean isInstalled() { | ||
| - return canExecute( TYPESETTER ); | ||
| } | ||
| -package com.keenwrite.util; | ||
| - | ||
| -import com.keenwrite.io.MediaType; | ||
| - | ||
| -import java.io.IOException; | ||
| -import java.nio.file.Path; | ||
| -import java.nio.file.Paths; | ||
| -import java.util.stream.Stream; | ||
| - | ||
| -import static com.keenwrite.Bootstrap.APP_TITLE_LOWERCASE; | ||
| -import static com.keenwrite.io.MediaTypeExtension.valueFrom; | ||
| -import static java.io.File.createTempFile; | ||
| -import static java.io.File.pathSeparator; | ||
| -import static java.lang.System.getenv; | ||
| -import static java.nio.file.Files.isExecutable; | ||
| -import static java.util.regex.Pattern.quote; | ||
| - | ||
| -/** | ||
| - * Place for common file-related functionality. | ||
| - */ | ||
| -public class FileUtils { | ||
| - /** | ||
| - * For finding executable programs. | ||
| - */ | ||
| - private static final String[] EXTENSIONS = new String[] | ||
| - {"", ".com", ".exe", ".bat", ".cmd"}; | ||
| - | ||
| - private FileUtils() {} | ||
| - | ||
| - /** | ||
| - * Creates a temporary file for the given {@link MediaType}, which will be | ||
| - * deleted when the application exits. | ||
| - * | ||
| - * @param media The type of file to create (i.e., its extension). | ||
| - * @return The fully qualified path to a file. | ||
| - * @throws IOException Could not create the temporary file. | ||
| - */ | ||
| - public static Path createTemporaryFile( final MediaType media ) | ||
| - throws IOException { | ||
| - final var file = createTempFile( | ||
| - APP_TITLE_LOWERCASE, '.' + valueFrom( media ).getExtension() ); | ||
| - file.deleteOnExit(); | ||
| - return file.toPath(); | ||
| - } | ||
| - | ||
| - /** | ||
| - * Given the name of an executable (without an extension) file, this will | ||
| - * attempt to determine whether the executable is found in the PATH | ||
| - * environment variable. | ||
| - * | ||
| - * @param exe The executable file name to find. | ||
| - * @return {@code true} when the given file name references an executable | ||
| - * file located in the PATH environment variable. | ||
| - */ | ||
| - public static boolean canExecute( final String exe ) { | ||
| - final var paths = getenv( "PATH" ).split( quote( pathSeparator ) ); | ||
| - return Stream.of( paths ).map( Paths::get ).anyMatch( | ||
| - path -> { | ||
| - final var p = path.resolve( exe ); | ||
| - | ||
| - for( final var extension : EXTENSIONS ) { | ||
| - if( isExecutable( Path.of( p.toString() + extension ) ) ) { | ||
| - return true; | ||
| - } | ||
| - } | ||
| - | ||
| - return false; | ||
| - } | ||
| - ); | ||
| - } | ||
| -} | ||
| Delta | 85 lines added, 90 lines removed, 5-line decrease |
|---|