![JAR search and dependency download from the Maven repository](/logo.png)
protoj.lang.StandardProject Maven / Gradle / Ivy
Show all versions of protoj-jdk6 Show documentation
/**
* Copyright 2009 Ashley Williams
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package protoj.lang;
import java.io.File;
import org.apache.log4j.Logger;
import protoj.lang.command.StandardCommands;
/**
* This is the starting point class for all projects that wish to take advantage
* of ProtoJ pure java use-cases from compilation and javadoc generation to
* installation and configuration. There is no need to construct any other
* protoj class other than this one as it is the domain object that aggregates
* all the others. Neither is there any need to write even one line of xml -
* that is unless you take advantage of the dependency download feature or
* artifact publish feature, which use the xml based ivy/maven API.
*
* Although there are many classes in the ProtoJ library many of them are inside
* packages qualified with *internal* which means they are implementation
* classes. This leaves little more than a couple of dozen pojos to get to grips
* with in order to gain an understanding of ProtoJ. You can find these classes
* directly under the protoj.lang
packages.
*
* To get started simply embed an instance of StandardProject in your own pojo
* and invoke the initXXX() methods for features that you wish to use and use
* the {@link CommandStore} domain object to add your own project specific
* commands. Here is a simple but complete example of a class called
* foo.Foo
:
*
*
* package protoj.lang.internal.sample;
*
* import protoj.lang.StandardProject;
*
* final class Foo {
* public static void main(String[] args) {
* StandardProject project = new StandardProject(args, "Foo Version 1.0");
* project.getCompileFeature().initConfig(false,
* new ArgRunnable<CompileFeature>() {
* public void run(CompileFeature feature) {
* feature.getJavacCompileTask().getCompileTask()
* .setMemoryMaximumSize("16m");
* feature.getJavacCompileTask().getCompileTask()
* .setSource("1.5");
* }
* });
* project.initJunit("16m");
* project.getArchiveFeature().initProjectArchive("foo", "foo-1.0-RC1");
* project.getArchiveFeature().addClasses("foo-1.0");
* project.getArchiveFeature().addSources("foo-1.0");
* project.getArchiveFeature().addJavadoc("foo-1.0", "16m");
* project.getCommandStore().addCommand("hello-foo",
* "writes to the console", "16m", new Runnable() {
* public void run() {
* System.out.println("Hello Foo!");
* }
* });
* project.getDispatchFeature().dispatchCommands();
* }
* }
*
*
* Take a look at {@link ProjectLayout} to find out more about the directory
* structure of a ProtoJ project and where the java code in particular should be
* placed. Be sure to modify the demo project though rather than creating a new
* project from scratch each time - do this by executing the no-dependencies
* ProtoJ jar file with java -jar
.
*
* In order to get to this world of pure java, some mechanism must take
* responsibility for compiling and running the application in the first place
* and one solution is to use a shell script. Check out demo.sh
and
* demo.bat
from the demo project for some examples. Here is the
* call to java from a typical bash shell script:
*
*
* java ... helloworld.HelloWorld "init --rootDir `pwd`/.. --scriptName $0" "$@"
*
*
* Note the special init
command is specified as an argument to
* java, with the mandatory --rootDir
and --scriptName
* options that protoj requires in order to function:
*
* And also note the use of the bash $@
place-holder so that
* additional commands such as compile
, jar
and
* test
can be specified at the command line.
*
* @author Ashley Williams
*
*/
public final class StandardProject {
/**
* See {@link #getPropertyStore()}
*/
private PropertyStore propertyStore;
/**
* See {@link #getDependencyStore()}
*/
private DependencyStore dependencyStore;
/**
* See {@link #getProperties()}
*/
private StandardProperties properties;
/**
* See {@link #getCommandStore()}
*/
private CommandStore commandStore;
/**
* See {@link #getCommands()}.
*/
private StandardCommands commands;
/**
* See {@link #getLayout()}.
*/
private ProjectLayout layout;
/**
* See {@link #getProtoLogger()}.
*/
private ProtoLogger protoLogger;
/**
* See {@link #getInstructionChain()}.
*/
private InstructionChain instructionChain;
/**
* See {@link #getRetrieveFeature()}.
*/
private RetrieveFeature retrieveFeature;
/**
* See {@link #getDispatchFeature()}.
*/
private DispatchFeature dispatchFeature;
/**
* See {@link #getCompileFeature()}.
*/
private CompileFeature compileFeature;
/**
* See {@link #getResourceFeature()}.
*/
private ResourceFeature resourceFeature;
/**
* See {@link #getInfoFeature()}.
*/
private InfoFeature infoFeature;
/**
* See {@link #getPublishFeature()}.
*/
private PublishFeature publishFeature;
/**
* See {@link #getJunitFeature()}.
*/
private JunitFeature junitFeature;
/**
* See {@link #getArchiveFeature()}.
*/
private ArchiveFeature archiveFeature;
/**
* See {@link #getUploadGoogleCodeFeature()}.
*/
private UploadGoogleCodeFeature uploadGoogleCodeFeature;
/**
* See {@link #getScpFeature()}.
*/
private ScpFeature scpFeature;
/**
* See {@link #getDirconfFeature()}.
*/
private DirconfFeature dirconfFeature;
/**
* See {@link #getVerifyTarFeature()}.
*/
private VerifyTarFeature verifyTarFeature;
/**
* See {@link #getScpconfFeature()}.
*/
private ScpconfFeature scpconfFeature;
/**
* Most projects should use this constructor.
*
* Parses arguments originating from main()
. The easiest way to
* describe the format is with an example:
*
*
* compile "find-alien -gx milky-way" --rootDir ˜/dev/myproj/ --scriptName alien.sh -Dprotoj.debug
*
*
* which results in the following args array elements:
*
*
* arg[0]="compile"
- command with no arguments
* arg[1]="find-alien -gx milky-way"
- command with a
* single argument
* arg[2]="--rootDir"
- the project root directory option
* name
* arg[3]="~/dev/myproj/"
- the project root directory
* option value
* arg[4]="--scriptName"
- the project script name option
* name
* arg[5]="alien.sh"
- the project script name option value
*
* arg[6]="-Dprotoj.debug"
- system property
*
* So in other words the two types of argument are commands and system
* properties. Also the rootDir and scriptName options are mandatory and
* used to calculate the project layout - see {@link InstructionChain} for
* more information
*
* Note that although -D
syntax is used for the vm arguments,
* these are not the same as the genuine vm arguments that won't appear in
* the args
parameter at all. This is because we need to store
* them so that they can successfully be passed to any new virtual machines
* that need starting.
*
* @param args
* these should be the arguments from main()
* @param versionInfo
* any information to be reported when the version command is
* invoked
*/
public StandardProject(String[] args, String versionInfo) {
this(new InstructionChain(args), versionInfo);
}
/**
* This constructor is useful in situations where the commands have to built
* up in-code rather than parsed from a command line. For example in unit
* tests and also in {@link VerifyTarFeature}.
*
* @param rootDir
* the root directory of the project
* @param scriptName
* the name of the script responsible for issuing commands - if
* no extension is given then ".bat" is assumed for windows and
* ".sh" otherwise
* @param versionInfo
* any information to be reported when the version command is
* invoked
*/
public StandardProject(File rootDir, String scriptName, String versionInfo) {
this(new InstructionChain(rootDir, scriptName), versionInfo);
}
/**
* This constructor gets the root dir and script name information from the
* protoj.rootDir and protoj.scriptName system properties configured by
* junit. So this constructor is intended for junit tests.
*
* @param versionInfo
*/
public StandardProject(String versionInfo) {
this(new File(System.getProperty("protoj.rootDir")), System
.getProperty("protoj.scriptName"), versionInfo);
}
/**
* Common implementation for all constructors.
*
* @param core
* @param versionInfo
*/
private StandardProject(InstructionChain instructionChain,
String versionInfo) {
this.instructionChain = instructionChain;
this.layout = new ProjectLayout(instructionChain.getRootDir(),
instructionChain.getScriptName());
this.protoLogger = new ProtoLogger(this);
this.commandStore = new CommandStore(this);
this.propertyStore = new PropertyStore(this);
this.dependencyStore = new DependencyStore(this);
this.properties = new StandardProperties(this);
this.dispatchFeature = new DispatchFeature(this);
this.resourceFeature = new ResourceFeature(this);
this.compileFeature = new CompileFeature(this);
this.retrieveFeature = new RetrieveFeature(this);
this.infoFeature = new InfoFeature(this, versionInfo);
this.verifyTarFeature = new VerifyTarFeature(this);
this.archiveFeature = new ArchiveFeature(this);
this.commands = new StandardCommands(this);
this.scpFeature = new ScpFeature(this);
}
/**
* This method must be called if you wish to be able to publish project
* artifacts created with the {@link ArchiveFeature} class.
*
* @param url
*/
public void initPublish(String url) {
this.publishFeature = new PublishFeature(this, url);
}
/**
* This method must be called if junit tests are required, in order to
* specify the amount of memory required. Invoke junit funtionality by first
* obtaining the delegate with a call to {@link #getJunitFeature()}.
*
* @param memory
* uses standard java tool notation, e.g. "32m"
*/
public void initJunit(String memory) {
this.junitFeature = new JunitFeature(this, memory);
}
/**
* This method must be called if configuration with properties files from a
* mounted directory is to be supported. Pass-thru method to
* {@link DirconfFeature#DirconfFeature(StandardProject)}.
*/
public void initDirConfig() {
this.dirconfFeature = new DirconfFeature(this);
}
/**
* This method must be called if configuration with properties files from a
* mounted directory is to be supported. Pass-thru method to
* {@link DirconfFeature#DirconfFeature(StandardProject, File)}.
*
* @param home
*/
public void initDirConfig(File home) {
this.dirconfFeature = new DirconfFeature(this, home);
}
/**
* This method must be called if configuration with properties files from a
* remotely located directory is to be supported. Pass-thru method to
* {@link ScpconfFeature#ScpconfFeature(StandardProject, String)} .
*
* @param parentUrl
*/
public void initScpConfig(String parentUrl) {
this.scpconfFeature = new ScpconfFeature(this, parentUrl);
}
/**
* This method must be called if the ability to upload the project tar file
* to google code is required. This is a pass-through method to
* {@link UploadGoogleCodeFeature#UploadGoogleCodeFeature(StandardProject, String)}
* , so see that constructor for a description of the parameters.
*
* Note that there is no corresponding out of the box command for this
* feature. That's because it would be too generic to be useful due to the
* many pieces of information that would need to be specified at the command
* line. Projects would be best served by writing their own commands with
* the information hardcoded, such as the artifact name etc.
*
* @param googleProjectName
*/
public void initUploadGoogleCode(String googleProjectName) {
uploadGoogleCodeFeature = new UploadGoogleCodeFeature(this,
googleProjectName);
}
/**
* Creates a helper that is able to drive the project represented by this
* class instance through its command line interface. Very useful for tests
* for example that need to go through the script as the user would.
*
* @return
*/
public ScriptSession createScriptSession() {
return new ScriptSession(getLayout().getShellScript());
}
/**
* A reference to the delegate object used to extract resources to the
* filing system for APIs that can only work in this way and also apply
* variable ${var} substitutions. See {@link ResourceFeature}.
*
* @return
*/
public ResourceFeature getResourceFeature() {
return resourceFeature;
}
/**
* A reference to the delegate object used to dispatch the instructions
* usually specified at the command line. See {@link DispatchFeature}.
*
* @return
*/
public DispatchFeature getDispatchFeature() {
return dispatchFeature;
}
/**
* A reference to the delegate object used to perform in-code compilation .
* See {@link CompileFeature}.
*
* @return
*/
public CompileFeature getCompileFeature() {
return compileFeature;
}
/**
* A reference to the delegate object used to download project dependencies.
* See {@link RetrieveFeature}.
*
* @return
*/
public RetrieveFeature getRetrieveFeature() {
return retrieveFeature;
}
/**
* A reference to the delegate object used to provide configuration
* functionality. See {@link JunitFeature}.
*
* @return
*/
public JunitFeature getJunitFeature() {
return junitFeature;
}
/**
* A reference to the delegate object used to provide archive creation
* functionality. See {@link ArchiveFeature}.
*
* @return
*/
public ArchiveFeature getArchiveFeature() {
return archiveFeature;
}
/**
* A reference to the delegate object used to provide configuration
* functionality. See {@link VerifyTarFeature}.
*
* @return
*/
public VerifyTarFeature getVerifyTarFeature() {
return verifyTarFeature;
}
/**
* A reference to the delegate object used to provide the google code upload
* functionality. See {@link UploadGoogleCodeFeature}.
*
* @return
*/
public UploadGoogleCodeFeature getUploadGoogleCodeFeature() {
return uploadGoogleCodeFeature;
}
/**
* A reference to the delegate object used to provide scp functionality. See
* {@link ScpFeature}.
*
* @return
*/
public ScpFeature getScpFeature() {
return scpFeature;
}
/**
* A reference to the delegate object used to provide configuration
* functionality. See {@link DirconfFeature}.
*
* @return
*/
public DirconfFeature getDirconfFeature() {
return dirconfFeature;
}
/**
* A reference to the delegate object used to provide configuration
* functionality. See {@link ScpconfFeature}.
*
* @return
*/
public ScpconfFeature getScpconfFeature() {
return scpconfFeature;
}
/**
* A reference to the delegate object used to provide project information
* functionality. See {@link InfoFeature}.
*
* @return
*/
public InfoFeature getInfoFeature() {
return infoFeature;
}
/**
* A reference to the delegate object used to publish project artifacts. See
* {@link PublishFeature}.
*
* @return
*/
public PublishFeature getPublishFeature() {
return publishFeature;
}
/**
* Access to the class responsible for containing all the instructions to be
* dispatched.
*
* @return
*/
public InstructionChain getInstructionChain() {
return instructionChain;
}
/**
* Delegated functionality, see {@link CommandStore}.
*
* @return
*/
public CommandStore getCommandStore() {
return commandStore;
}
/**
* A container of references of those commands belonging to this project
* that have been added to the {@link CommandStore}.
*
* @return
*/
public StandardCommands getCommands() {
return commands;
}
/**
* A container of project dependencies belonging to this project. See
* {@link DependencyStore}.
*
* @return
*/
public DependencyStore getDependencyStore() {
return dependencyStore;
}
/**
* Delegated functionality, see {@link PropertyStore}.
*
* @return
*/
public PropertyStore getPropertyStore() {
return propertyStore;
}
/**
* A container of references of those properties belonging to this
* StandardProject that have been added to the {@link PropertyStore}.
*
* @return
*/
public StandardProperties getProperties() {
return properties;
}
/**
* Delegated functionality, see {@link ProtoLogger}.
*
* @return
*/
public ProtoLogger getProtoLogger() {
return protoLogger;
}
/**
* Access to the protoj log4j instance. Convenient short-hand for
* getProtoLogger().getProtoLogger()
.
*
* @return
*/
public Logger getLogger() {
return protoLogger.getProtoLogger();
}
/**
* Delegated functionality, see {@link ProjectLayout}.
*
* @return
*/
public ProjectLayout getLayout() {
return layout;
}
/**
* True if version 6, otherwise version 5 is assumed. ProtoJ doesn't support
* lesser versions.
*
* @return
*/
public boolean isJdk6() {
String version = System.getProperty("java.specification.version");
return version.contains("6");
}
/**
* The ProtoJ project version number.
*
* @return
*/
public String getProtojVersion() {
return "1.9.2";
}
}