/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.muse.tools.generator.projectizer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.apache.muse.tools.generator.Wsdl2Java;
import org.apache.muse.tools.generator.util.OverwriteHelper;
import org.apache.muse.util.FileUtils;
import org.apache.muse.util.messages.Messages;
import org.apache.muse.util.messages.MessagesFactory;
import org.apache.muse.util.xml.XmlUtils;
import org.apache.muse.ws.addressing.WsaConstants;
import org.apache.muse.ws.notification.WsnConstants;
import org.apache.muse.ws.resource.metadata.MetadataDescriptor;
import org.apache.muse.ws.resource.metadata.WsrmdConstants;
import org.apache.muse.ws.resource.sg.WssgConstants;
import org.apache.muse.ws.wsdl.WsdlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* AbstractProjectizer contains methods that are
* useful to projectizers built so far.
*
* @author Andrew Eberbach (aeberbac)
*/
public abstract class AbstractProjectizer implements Projectizer {
/**
* Message bundle for localized messages
*/
private static Messages _MESSAGES = MessagesFactory.get(AbstractProjectizer.class);
/**
* A logger to which we will log messages
*/
private static Logger _logger = Logger.getLogger(Wsdl2Java.class.getPackage().getName());
/**
* The default extension for WSDL files.
*/
protected static final String DEFAULT_WSDL_NAME_SUFFIX = ".wsdl";
protected static final String DEFAULT_RMD_NAME_SUFFIX = ".rmd";
/**
* A placeholder in strings that can be replaced with a specific string.
*/
protected static final String PLACE_HOLDER = "XXX";
/**
* A low-tech way of keeping track of the resource instances that the projectizer
* can create.
*/
private int _resourceCounter = 1;
/**
* A class that will determine if a given file can be overwritten
* if it already exists.
*/
private OverwriteHelper _overwriteHelper = null;
/**
* The target base directory in which the projectizer will projectize.
*/
protected File _targetDirectory;
/**
* Serializes an XML node and writes it out to a file provided that
* the file doesn't already exist, and if it does then the _overwrite
* variable must be set to true.
*
* @param node
* The DOM node to write out
* @param destination
* The file where this should be written
*
* @throws Exception
* If anything goes wrong
*/
protected void writeToFileCheck(Node node, File destination) throws Exception {
if (canOverwrite(destination)) {
checkParentDirectory(destination);
writeStringtoFile(XmlUtils.toString(node), destination);
_overwriteHelper.add(destination, _targetDirectory);
} else {
_logger.info(_MESSAGES.get("NotOverwriting", new String[] {destination.getPath()}));
}
}
protected void writeToFileCheck(String string, File destination) throws Exception {
writeToFileCheck(string, destination, true);
}
/**
* Writes a string to a file provided that
* the file doesn't already exist, and if it does then the _overwrite
* variable must be set to true.
*
* @param string
* The string to write out
* @param destination
* The file where this should be written
* @param overwritable
* Flag to see if this filename should be passed to the OverwriteHelper
*
* @throws Exception
* If anything goes wrong
*/
protected void writeToFileCheck(String string, File destination, boolean overwritable) throws Exception {
if (canOverwrite(destination)) {
checkParentDirectory(destination);
writeStringtoFile(string, destination);
if(overwritable) {
_overwriteHelper.add(destination, _targetDirectory);
}
} else {
_logger.info(_MESSAGES.get("NotOverwriting", new String[] {destination.getPath()}));
}
}
/**
* Writes an <code>InputStream</code> to a file provided that
* the file doesn't already exist, and if it does then the _overwrite
* variable must be set to true.
*
* @param inputStream
* The <code>InputStream</code> to write out
* @param destination
* The file where this should be written
*
* @throws Exception
* If anything goes wrong
*/
protected void copyStreamCheck(InputStream inputStream, File destination) throws Exception {
if(canOverwrite(destination)) {
checkParentDirectory(destination);
FileUtils.copyFile(inputStream,destination);
_overwriteHelper.add(destination, _targetDirectory);
} else {
_logger.warning(_MESSAGES.get("NotOverwriting", new String[] {destination.getPath()}));
}
}
/**
* Read an <code>InputStream</code> replacing all occurences of PLACE_HOLDER
* with the values provided in the filler.
*
* @param inputStream
* The source input
* @param filler
* The filler for the string template
*
* @return
* A string with as many PLACE_HOLDERs replaced as possible
*
* @throws Exception
* If anything goes wrong
*/
protected String loadString(InputStream inputStream, Object[] filler) throws Exception {
StringBuffer result = new StringBuffer();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
int i=0;
while( (line = br.readLine()) != null) {
if(line.indexOf(PLACE_HOLDER) > 0) {
if(i < filler.length) {
line = line.replaceFirst(PLACE_HOLDER, filler[i++].toString());
}
}
result.append(line + "\n");
}
return result.toString();
}
/**
* Copies all of the files (recursively) from the source folder into
* the parent folder.
*
* @param sourceDir
* The source folder
* @param destinationDir
* The destination, ie what the folder will be called
*
* @throws Exception
*/
protected void copyTemplate(File sourceDir, File destinationDir) throws Exception {
File[] files = sourceDir.listFiles();
File destination = null;
for(int i=0; i < files.length; i++) {
destination = new File(destinationDir, files[i].getName());
if(files[i].isDirectory()) {
checkDirectory(destination);
copyTemplate(files[i], destination);
} else {
copyFileCheck(files[i], destination);
}
}
}
/**
* Copy a file from the source file to the destination performing
* an overwrite check.
*
* @param source
* @param destination
* @throws Exception
*/
private void copyFileCheck(File source, File destination) throws Exception {
if (canOverwrite(destination)) {
checkParentDirectory(destination);
FileUtils.copy(source, destination);
_overwriteHelper.add(destination, _targetDirectory);
} else {
_logger.info(_MESSAGES.get("NotOverwriting", new String[] {destination.getPath()}));
}
}
/**
* Returns true if the given file can be overwritten if it exists. This
* is delegated to the OverwriteHelper.
*
* @param file The file to check
* @return True if it can be overwritten
*/
private boolean canOverwrite(File file) {
return _overwriteHelper.canOverwrite(file, _targetDirectory);
}
/**
* Create a router entry for the given service in the given directory. This
* will generate a router entry using a simple integer counter for the file name
* and it will contain an empty ReferenceParameters element.
*
* @param routerEntriesDir
* The directory where the router entries should be created
* @param serviceName
* The name of the service
*
* @throws Exception
* If anything goes wrong
*/
protected void createRouterEntries(File routerEntriesDir, String serviceName, Map capabilities) throws Exception{
//
// no pre-determined instances for subscriptions or SG entries
//
if (capabilities.keySet().contains(WsnConstants.SUBSCRIPTION_MGR_URI) ||
capabilities.keySet().contains(WssgConstants.ENTRY_URI))
return;
Document routerEntryDocument = XmlUtils.createDocument();
Element parametersElement = XmlUtils.createElement(routerEntryDocument, WsaConstants.PARAMETERS_QNAME);
routerEntryDocument.appendChild(parametersElement);
File serviceDir = new File(routerEntriesDir, serviceName);
File routerEntryFile = new File(serviceDir, getResourceFileName());
writeToFileCheck(routerEntryDocument, routerEntryFile);
}
/**
* Get the name of the next router entry file. This is done
* by using an integer counter and creating a name out of it.
*
* For example:
* resource-instance-1.xml
* resource-instance-2.xml
*
* and so on.
*
* @return The next available name
*/
private String getResourceFileName() {
return Axis2ProjectizerConstants.RESOURCE_FILE.replaceFirst(PLACE_HOLDER, String.valueOf(_resourceCounter++));
}
/**
* Given a list of Maps (mapping file names to file contents) write the files
* to the target directory.
*
* @param javaSourceDir
* The target directory
*
* @param filesMaps
* A list of Maps which map file names to file content
*
* @throws Exception
* If anything goes wrong
*/
protected void createJavaSources(File javaSourceDir, Map[] filesMaps) throws Exception {
createJavaSources(javaSourceDir, filesMaps, null);
}
/**
* Given a list of Maps (mapping file names to file contents) write the files
* to the target directory.
*
* @param javaSourceDir
* The target directory
*
* @param filesMaps
* A list of Maps which map file names to file content
* @param ignoreSets
* A list of sets of files to not include in the overwrite manifest
*
* @throws Exception
* If anything goes wrong
*/
protected void createJavaSources(File javaSourceDir, Map[] filesMaps, Set[] ignoreSets) throws Exception {
for(int i = 0; i < filesMaps.length; i++) {
Map files = filesMaps[i];
for (Iterator j = files.keySet().iterator(); j.hasNext();) {
String file = (String) j.next();
File javaFile = new File(javaSourceDir, file);
boolean overwritable = true;
if(ignoreSets != null && ignoreSets[i] != null) {
overwritable = !ignoreSets[i].contains(new File(file));
}
writeToFileCheck((String) files.get(file), javaFile, overwritable);
}
}
}
/**
* Utility method for copying jars from the Muse distribution. The
* module names serve as names of directories (ie. core, tools, and so on). The
* baseModulesDir is where to start from (ie. c:\muse-2.0\modules). All of the jars
* in each modulename directory are copied to the destDir.
*
* @param moduleNames
* The modules to copy
*
* @param baseModulesDir
* The location where the modules reside
*
* @param destDir
* The destination directory
*
* @throws IOException
* If anything goes wrong
*/
protected void copyJars(String[] moduleNames, File baseModulesDir, File destDir) throws Exception {
copyJars(moduleNames, baseModulesDir, destDir, null);
}
protected void copyJars(String[] moduleNames, File baseModulesDir, File destDir, FileFilter filter) throws Exception {
if(!baseModulesDir.exists()) {
throw new FileNotFoundException();
}
if(!destDir.exists()) {
if(!destDir.mkdirs()) {
throw new RuntimeException();
}
}
File curDir = null;
File destFile = null;
for(int i=0; i < moduleNames.length; i++) {
curDir = new File(baseModulesDir, moduleNames[i]);
if(!curDir.exists()) {
throw new FileNotFoundException(curDir.getAbsolutePath());
}
//
// a null filter will return all files
//
File[] files = curDir.listFiles(filter);
for(int j=0; j < files.length; j++) {
if(files[j].getName().toLowerCase().endsWith(".jar")) {
destFile = new File(destDir, files[j].getName());
copyFileCheck(files[j], destFile);
}
}
}
}
/**
* Write a string to a file without doing any overwrite checks.
*
* @param string The string to write
* @param destination The file into which to write the string
*
* @throws Exception
*/
protected void writeStringtoFile(String string, File destination) throws Exception {
FileWriter fileWriter = new FileWriter(destination);
fileWriter.write(string);
fileWriter.close();
}
/**
* Check to make sure that the parent directory of a given file exists
* or can be created. If it can be created, then try to make the directory.
*
* @param destination Target file to check
*
* @throws Exception
*/
protected void checkParentDirectory(File destination) throws Exception {
File parent = destination.getAbsoluteFile().getParentFile();
checkDirectory(parent);
}
/**
* Check to make sure that the given directory exists
* or can be created. If it can be created, then try to make the directory.
*
* @param directory Target directory to check
*
* @throws Exception
*/
protected void checkDirectory(File directory) throws Exception {
if(!directory.exists()) {
if(!directory.mkdirs()) {
Object[] filler = { directory } ;
throw new Exception(_MESSAGES.get("CouldNotMakeDir",filler));
}
}
}
/**
* Set the target directory for this projectizer. Also
* load an OverwriteHelper to keep track of which files
* can be overwritten.
*
* @param targetDirectory The target directory for the projectizer
* @param overwrite Flag to determine if every conflicting file should be overwritten
*/
protected void setTargetDirectory(File targetDirectory, boolean overwrite) {
_targetDirectory =
targetDirectory == null
?FileUtils.CURRENT_DIR
:targetDirectory;
_overwriteHelper = new OverwriteHelper(_targetDirectory, overwrite);
}
/**
* Create the overwrite manifest for this projectizer. Writes out
* the current list of files from the OverwriteHelper.
*
* @throws Exception
*/
protected void createOverwriteManifest() throws Exception {
_overwriteHelper.writeToDirectory(_targetDirectory);
}
protected String getWsdlFileName(String wsdlRelativePath, Document wsdl) {
String wsdlFileName = WsdlUtils.getServiceName(wsdl.getDocumentElement()) + DEFAULT_WSDL_NAME_SUFFIX;
return createClassloadablePath(wsdlRelativePath, wsdlFileName);
}
protected String getMetadataFileName(String wsdlRelativePath, Document wsdl) {
String rmdFileName = WsdlUtils.getServiceName(wsdl.getDocumentElement()) + DEFAULT_RMD_NAME_SUFFIX;
return createClassloadablePath(wsdlRelativePath, rmdFileName);
}
protected String createClassloadablePath(String directory, String filename) {
//
// Let java.io.File deal with the logic of path separators. We'll just
// make sure we settle on the forward slash separator after the dust clears
//
File file = new File(directory, filename);
return file.getPath().replace(File.separatorChar, '/');
}
protected void updatePortType(Document wsdl, MetadataDescriptor metadata, File metadataFile) {
Element portType = WsdlUtils.getFirstPortType(wsdl);
portType.setAttributeNS(WsrmdConstants.NAMESPACE_URI, WsrmdConstants.DESCRIPTOR_ATTR_QNAME.getLocalPart(), metadata.getName());
portType.setAttributeNS(WsrmdConstants.NAMESPACE_URI, WsrmdConstants.DESCRIPTOR_LOCATION_ATTR_QNAME.getLocalPart(), metadataFile.getName());
}
}