Java tutorial
/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License, version 2 as published by the Free Software * Foundation. * * You should have received a copy of the GNU General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * * Copyright 2006 - 2013 Pentaho Corporation. All rights reserved. */ package org.pentaho.platform.plugin.services.importexport; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.WebResource.Builder; import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig; import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; import com.sun.jersey.api.json.JSONConfiguration; import com.sun.jersey.core.header.FormDataContentDisposition; import com.sun.jersey.multipart.FormDataMultiPart; import com.sun.org.apache.xml.internal.security.encryption.EncryptedData; import com.sun.xml.ws.developer.JAXWSProperties; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.platform.api.repository2.unified.IUnifiedRepository; import org.pentaho.platform.plugin.services.messages.Messages; import org.pentaho.platform.repository.RepositoryFilenameUtils; import org.pentaho.platform.repository2.unified.webservices.jaxws.IUnifiedRepositoryJaxwsWebService; import org.pentaho.platform.repository2.unified.webservices.jaxws.UnifiedRepositoryToWebServiceAdapter; import org.pentaho.platform.security.policy.rolebased.actions.AdministerSecurityAction; import org.pentaho.platform.util.RepositoryPathEncoder; import org.pentaho.di.core.encryption.KettleTwoWayPasswordEncoder; import javax.ws.rs.core.MediaType; import javax.xml.namespace.QName; import javax.xml.ws.BindingProvider; import javax.xml.ws.Service; import javax.xml.ws.soap.SOAPBinding; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; /** * Handles the parsing of command line arguments and creates an import process based upon them * * @author <a href="mailto:dkincade@pentaho.com">David M. Kincade</a> */ public class CommandLineProcessor { private static final String API_REPO_FILES_IMPORT = "/api/repo/files/import"; private static final String ANALYSIS_DATASOURCE_IMPORT = "/plugin/data-access/api/mondrian/postAnalysis"; private static final String METADATA_DATASOURCE_IMPORT = "/plugin/data-access/api/metadata/postimport"; private static final String METADATA_DATASOURCE_EXT = "xmi"; private static final String ZIP_EXT = "zip"; private static final Log log = LogFactory.getLog(CommandLineProcessor.class); private static final Options options = new Options(); private static Exception exception; private CommandLine commandLine; private RequestType requestType; private IUnifiedRepository repository; private static enum RequestType { HELP, IMPORT, EXPORT, REST } private static enum DatasourceType { JDBC, METADATA, ANALYSIS } private static enum ResourceType { SOLUTIONS, DATASOURCE } private static Client client = null; static { // create the Options options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_HELP_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_HELP_NAME"), false, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_HELP_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_IMPORT_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_IMPORT_NAME"), false, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_IMPORT_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_EXPORT_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_EXPORT_NAME"), false, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_EXPORT_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_USERNAME_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_USERNAME_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_USERNAME_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PASSWORD_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PASSWORD_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PASSWORD_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_CHARSET_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_CHARSET_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_CHARSET_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_LOGFILE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_LOGFILE_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_LOGFILE_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PATH_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PATH_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PATH_DESCRIPTION")); // import only ACL additions options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_OVERWRITE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_OVERWRITE_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_OVERWRITE_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PERMISSION_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PERMISSION_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PERMISSION_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RETAIN_OWNERSHIP_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RETAIN_OWNERSHIP_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RETAIN_OWNERSHIP_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_WITH_MANIFEST_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_WITH_MANIFEST_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_WITH_MANIFEST_DESCRIPTION")); // rest services options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_REST_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_REST_NAME"), false, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_REST_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_SERVICE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_SERVICE_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_SERVICE_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PARAMS_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PARAMS_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PARAMS_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RESOURCE_TYPE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RESOURCE_TYPE_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RESOURCE_TYPE_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_DATASOURCE_TYPE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_DATASOURCE_TYPE_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_DATASOURCE_TYPE_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_DATASOURCE_TYPE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_DATASOURCE_TYPE_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RESOURCE_TYPE_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_DATASOURCE_TYPE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_DATASOURCE_TYPE_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_DATASOURCE_TYPE_DESCRIPTION")); options.addOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_CATALOG_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_CATALOG_NAME"), true, Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_CATALOG_DESCRIPTION")); options.addOption( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_DATASOURCE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_DATASOURCE_NAME"), true, Messages.getInstance() .getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_DATASOURCE_DESCRIPTION")); options.addOption( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_XMLA_ENABLED_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_XMLA_ENABLED_NAME"), true, Messages.getInstance() .getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_XMLA_ENABLED_DESCRIPTION")); options.addOption( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_METADATA_DOMAIN_ID_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_METADATA_DOMAIN_ID_NAME"), true, Messages.getInstance() .getString("CommandLineProcessor.INFO_OPTION_METADATA_DOMAIN_ID_DESCRIPTION")); } /** * How this class is executed from the command line. * * @param args */ public static void main(String[] args) throws Exception { try { // reset the exception information exception = null; final CommandLineProcessor commandLineProcessor = new CommandLineProcessor(args); // new service only switch (commandLineProcessor.getRequestType()) { case HELP: printHelp(); break; case IMPORT: commandLineProcessor.performImport(); break; case EXPORT: commandLineProcessor.performExport(); break; case REST: commandLineProcessor.performREST(); break; } } catch (ParseException parseException) { exception = parseException; System.err.println(parseException.getLocalizedMessage()); System.out.println(parseException.getLocalizedMessage()); printHelp(); log.error(parseException.getMessage(), parseException); } catch (Exception e) { exception = e; e.printStackTrace(); log.error(e.getMessage(), e); } } /** * call FileResource REST service example: {path+}/children example: {path+}/parameterizable example: * {path+}/properties example: /delete?params={fileid1, fileid2} * * @throws ParseException */ private void performREST() throws ParseException, InitializationException { String contextURL = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_NAME"), true, false); String path = getOptionValue(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PATH_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PATH_NAME"), true, false); String logFile = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_LOGFILE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_LOGFILE_NAME"), false, true); String exportURL = contextURL + "/api/repo/files/"; if (path != null) { String effPath = RepositoryPathEncoder.encodeRepositoryPath(path); exportURL += effPath; } String service = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_SERVICE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_SERVICE_NAME"), true, false); String params = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PARAMS_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PARAMS_NAME"), false, true); exportURL += "/" + service; if (params != null) { exportURL += "?params=" + params; } initRestService(); WebResource resource = client.resource(exportURL); // Response response Builder builder = resource.type(MediaType.APPLICATION_JSON).type(MediaType.TEXT_XML_TYPE); ClientResponse response = builder.put(ClientResponse.class); if (response != null && response.getStatus() == 200) { String message = Messages.getInstance().getString("CommandLineProcessor.INFO_REST_COMPLETED") .concat("\n"); message += Messages.getInstance().getString("CommandLineProcessor.INFO_REST_RESPONSE_STATUS", response.getStatus()); message += "\n"; if (logFile != null && !"".equals(logFile)) { message += Messages.getInstance().getString("CommandLineProcessor.INFO_REST_FILE_WRITTEN", logFile); System.out.println(message); writeFile(message, logFile); } } else { System.out.println( Messages.getInstance().getErrorString("CommandLineProcessor.ERROR_0002_INVALID_RESPONSE")); } } /** * Used only for REST Jersey calls * * @throws ParseException */ private void initRestService() throws ParseException, InitializationException { // get information about the remote connection String username = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_USERNAME_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_USERNAME_NAME"), true, false); String password = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PASSWORD_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PASSWORD_NAME"), true, false); password = KettleTwoWayPasswordEncoder.decryptPasswordOptionallyEncrypted(password); ClientConfig clientConfig = new DefaultClientConfig(); clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); client = Client.create(clientConfig); client.addFilter(new HTTPBasicAuthFilter(username, password)); // check if the user has permissions to upload/download data String contextURL = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_NAME"), true, false); WebResource resource = client.resource( contextURL + "/api/authorization/action/isauthorized?authAction=" + AdministerSecurityAction.NAME); String response = resource.get(String.class); if (!response.equals("true")) { throw new InitializationException( Messages.getInstance().getString("CommandLineProcessor.ERROR_0006_NON_ADMIN_CREDENTIALS")); } } /** * Returns information about any exception encountered (if one was generated) * * @return the {@link Exception} that was generated, or {@code null} if none was generated */ public static Exception getException() { return exception; } /** * Parses the command line and handles the situation where it isn't a valid import or export or rest request * * @param args * the command line arguments * @throws ParseException * indicates that neither (or both) an import and/or export have been request */ protected CommandLineProcessor(String[] args) throws ParseException { // parse the command line arguments commandLine = new PosixParser().parse(options, args); if (commandLine.hasOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_HELP_NAME")) || commandLine .hasOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_HELP_KEY"))) { requestType = RequestType.HELP; } else { if (commandLine .hasOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_REST_NAME")) || commandLine.hasOption( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_REST_KEY"))) { requestType = RequestType.REST; } else { final boolean importRequest = commandLine .hasOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_IMPORT_KEY")); final boolean exportRequest = commandLine .hasOption(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_EXPORT_KEY")); if (importRequest == exportRequest) { throw new ParseException(Messages.getInstance() .getErrorString("CommandLineProcessor.ERROR_0003_PARSE_EXCEPTION")); } requestType = (importRequest ? RequestType.IMPORT : RequestType.EXPORT); } } } // ========================== Instance Members / Methods // ========================== protected RequestType getRequestType() { return requestType; } /** * --import --url=http://localhost:8080/pentaho --username=admin --password=password --file-path=metadata.xmi * --resource-type=DATASOURCE --datasource-type=METADATA --overwrite=true --metadata-domain-id=steel-wheels * * @param contextURL * @param metadataDatasourceFile * @param overwrite * @throws ParseException * @throws IOException */ private void performMetadataDatasourceImport(String contextURL, File metadataDatasourceFile, String overwrite) throws ParseException, IOException { File metadataFileInZip = null; InputStream metadataFileInZipInputStream = null; String metadataImportURL = contextURL + METADATA_DATASOURCE_IMPORT; String domainId = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_METADATA_DOMAIN_ID_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_METADATA_DOMAIN_ID_NAME"), true, false); WebResource resource = client.resource(metadataImportURL); FormDataMultiPart part = new FormDataMultiPart(); final String name = RepositoryFilenameUtils.separatorsToRepository(metadataDatasourceFile.getName()); final String ext = RepositoryFilenameUtils.getExtension(name); try { if (ext.equals(ZIP_EXT)) { ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(metadataDatasourceFile)); ZipEntry entry = zipInputStream.getNextEntry(); while (entry != null) { final String entryName = RepositoryFilenameUtils.separatorsToRepository(entry.getName()); final String extension = RepositoryFilenameUtils.getExtension(entryName); File tempFile = null; boolean isDir = entry.getSize() == 0; if (!isDir) { tempFile = File.createTempFile("zip", null); tempFile.deleteOnExit(); FileOutputStream fos = new FileOutputStream(tempFile); IOUtils.copy(zipInputStream, fos); fos.close(); } if (extension.equals(METADATA_DATASOURCE_EXT)) { if (metadataFileInZip == null) { metadataFileInZip = new File(entryName); metadataFileInZipInputStream = new FileInputStream(metadataFileInZip); } } zipInputStream.closeEntry(); entry = zipInputStream.getNextEntry(); } zipInputStream.close(); part.field("overwrite", "true".equals(overwrite) ? "true" : "false", MediaType.MULTIPART_FORM_DATA_TYPE); part.field("domainId", domainId, MediaType.MULTIPART_FORM_DATA_TYPE).field("metadataFile", metadataFileInZipInputStream, MediaType.MULTIPART_FORM_DATA_TYPE); // If the import service needs the file name do the following. part.getField("metadataFile").setContentDisposition(FormDataContentDisposition.name("metadataFile") .fileName(metadataFileInZip.getName()).build()); // Response response ClientResponse response = resource.type(MediaType.MULTIPART_FORM_DATA).post(ClientResponse.class, part); if (response != null) { String message = response.getEntity(String.class); System.out.println(Messages.getInstance() .getString("CommandLineProcessor.INFO_REST_RESPONSE_RECEIVED", message)); } } else { FileInputStream metadataDatasourceInputStream = new FileInputStream(metadataDatasourceFile); part.field("overwrite", "true".equals(overwrite) ? "true" : "false", MediaType.MULTIPART_FORM_DATA_TYPE); part.field("domainId", domainId, MediaType.MULTIPART_FORM_DATA_TYPE).field("metadataFile", metadataDatasourceInputStream, MediaType.MULTIPART_FORM_DATA_TYPE); // If the import service needs the file name do the following. part.getField("metadataFile").setContentDisposition(FormDataContentDisposition.name("metadataFile") .fileName(metadataDatasourceFile.getName()).build()); // Response response ClientResponse response = resource.type(MediaType.MULTIPART_FORM_DATA).post(ClientResponse.class, part); if (response != null) { String message = response.getEntity(String.class); System.out.println(Messages.getInstance() .getString("CommandLineProcessor.INFO_REST_RESPONSE_RECEIVED", message)); } metadataDatasourceInputStream.close(); } } finally { metadataFileInZipInputStream.close(); part.cleanup(); } } /** * --import --url=http://localhost:8080/pentaho --username=admin --password=password * --file-path=analysis/steelwheels.mondrian.xml --resource-type=DATASOURCE --datasource-type=ANALYSIS * --overwrite=true --analysis-datasource=steelwheels * * @param contextURL * @param analysisDatasourceFile * @param overwrite * @throws ParseException * @throws IOException */ private void performAnalysisDatasourceImport(String contextURL, File analysisDatasourceFile, String overwrite) throws ParseException, IOException { String analysisImportURL = contextURL + ANALYSIS_DATASOURCE_IMPORT; String catalogName = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_CATALOG_Key"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_CATALOG_NAME"), false, true); String datasourceName = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_DATASOURCE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_DATASOURCE_NAME"), false, true); String xmlaEnabledFlag = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_ANALYSIS_XMLA_ENABLED_KEY"), Messages.getInstance().getString( "CommandLineProcessor.INFO_OPTION_DATASOURCE_ANALYSIS_XMLA_ENABLED_NAME"), false, true); WebResource resource = client.resource(analysisImportURL); FileInputStream inputStream = new FileInputStream(analysisDatasourceFile); String parms = "Datasource=" + datasourceName + ";overwrite=" + overwrite; FormDataMultiPart part = new FormDataMultiPart(); part.field("overwrite", "true".equals(overwrite) ? "true" : "false", MediaType.MULTIPART_FORM_DATA_TYPE); if (catalogName != null) { part.field("catalogName", catalogName, MediaType.MULTIPART_FORM_DATA_TYPE); } if (datasourceName != null) { part.field("datasourceName", datasourceName, MediaType.MULTIPART_FORM_DATA_TYPE); } part.field("parameters", parms, MediaType.MULTIPART_FORM_DATA_TYPE); part.field("xmlaEnabledFlag", "true".equals(xmlaEnabledFlag) ? "true" : "false", MediaType.MULTIPART_FORM_DATA_TYPE); part.field("uploadAnalysis", inputStream, MediaType.MULTIPART_FORM_DATA_TYPE); // If the import service needs the file name do the following. part.getField("uploadAnalysis").setContentDisposition(FormDataContentDisposition.name("uploadAnalysis") .fileName(analysisDatasourceFile.getName()).build()); // Response response ClientResponse response = resource.type(MediaType.MULTIPART_FORM_DATA).post(ClientResponse.class, part); if (response != null) { String message = response.getEntity(String.class); response.close(); System.out.println( Messages.getInstance().getString("CommandLineProcessor.INFO_REST_RESPONSE_RECEIVED", message)); } inputStream.close(); part.cleanup(); } /** * @throws ParseException * @throws IOException */ private void performDatasourceImport() throws ParseException, IOException { String contextURL = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_Key"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_NAME"), true, false); String filePath = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_NAME"), true, false); String datasourceType = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_DATASOURCE_TYPE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_DATASOURCE_TYPE_NAME"), true, false); String overwrite = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_OVERWRITE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_OVERWRITE_NAME"), false, true); /* * wrap in a try/finally to ensure input stream is closed properly */ try { initRestService(); File file = new File(filePath); if (datasourceType != null) { if (datasourceType.equals(DatasourceType.ANALYSIS.name())) { performAnalysisDatasourceImport(contextURL, file, overwrite); } else if (datasourceType.equals(DatasourceType.METADATA.name())) { performMetadataDatasourceImport(contextURL, file, overwrite); } } } catch (Exception e) { System.err.println(e.getMessage()); log.error(e.getMessage()); } } /* * --import --url=http://localhost:8080/pentaho - -username=admin --password=password * --charset=UTF-8 --path=:public --file-path=C:/Users/tband/Downloads/pentaho-solutions.zip * --logfile=c:/Users/tband/Desktop/logfile.log --permission=true --overwrite=true --retainOwnership=true (required * fields- default is false) */ private void performImport() throws ParseException, IOException { String contextURL = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_Key"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_NAME"), true, false); String filePath = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_NAME"), true, false); String resourceType = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RESOURCE_TYPE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RESOURCE_TYPE_NAME"), false, true); // We are importing datasources if (resourceType != null && resourceType.equals(ResourceType.DATASOURCE.name())) { performDatasourceImport(); } else { String charSet = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_CHARSET_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_CHARSET_NAME"), false, true); String logFile = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_LOGFILE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_LOGFILE_NAME"), false, true); String path = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PATH_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PATH_NAME"), true, false); String importURL = contextURL + API_REPO_FILES_IMPORT; File fileIS = new File(filePath); InputStream in = new FileInputStream(fileIS); FormDataMultiPart part = new FormDataMultiPart(); /* * wrap in a try/finally to ensure input stream is closed properly */ try { initRestService(); WebResource resource = client.resource(importURL); String overwrite = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_OVERWRITE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_OVERWRITE_NAME"), true, false); String retainOwnership = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RETAIN_OWNERSHIP_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_RETAIN_OWNERSHIP_NAME"), true, false); String permission = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PERMISSION_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PERMISSION_NAME"), true, false); part.field("importDir", path, MediaType.MULTIPART_FORM_DATA_TYPE); part.field("overwriteAclPermissions", "true".equals(overwrite) ? "true" : "false", MediaType.MULTIPART_FORM_DATA_TYPE); part.field("retainOwnership", "true".equals(retainOwnership) ? "true" : "false", MediaType.MULTIPART_FORM_DATA_TYPE); part.field("charSet", charSet == null ? "UTF-8" : charSet); part.field("applyAclPermissions", "true".equals(permission) ? "true" : "false", MediaType.MULTIPART_FORM_DATA_TYPE) .field("fileUpload", in, MediaType.MULTIPART_FORM_DATA_TYPE); // If the import service needs the file name do the following. part.field("fileNameOverride", fileIS.getName(), MediaType.MULTIPART_FORM_DATA_TYPE); part.getField("fileUpload").setContentDisposition( FormDataContentDisposition.name("fileUpload").fileName(fileIS.getName()).build()); // Response response ClientResponse response = resource.type(MediaType.MULTIPART_FORM_DATA).post(ClientResponse.class, part); if (response != null) { String message = response.getEntity(String.class); System.out.println(Messages.getInstance() .getString("CommandLineProcessor.INFO_REST_RESPONSE_RECEIVED", message)); if (logFile != null && !"".equals(logFile)) { writeFile(message, logFile); } response.close(); } } catch (Exception e) { System.err.println(e.getMessage()); log.error(e.getMessage()); writeFile(e.getMessage(), logFile); } finally { // close input stream and cleanup the jersey resources client.destroy(); part.cleanup(); in.close(); } } } /** * REST Service Export * * @throws ParseException * --export --url=http://localhost:8080/pentaho --username=admin --password=password * --file-path=c:/temp/export.zip --charset=UTF-8 --path=public/pentaho-solutions/steel-wheels * --logfile=c:/temp/steel-wheels.log --withManifest=true * @throws java.io.IOException */ private void performExport() throws ParseException, IOException, InitializationException { String contextURL = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_NAME"), true, false); String path = getOptionValue(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PATH_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PATH_NAME"), true, false); String withManifest = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_WITH_MANIFEST_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_WITH_MANIFEST_NAME"), false, true); String effPath = RepositoryPathEncoder.encodeURIComponent(RepositoryPathEncoder.encodeRepositoryPath(path)); if (effPath.lastIndexOf(":") == effPath.length() - 1 // remove trailing slash && effPath.length() > 1) { // allow user to enter "--path=/" effPath = effPath.substring(0, effPath.length() - 1); } String logFile = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_LOGFILE_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_LOGFILE_NAME"), false, true); String exportURL = contextURL + "/api/repo/files/" + effPath + "/download?withManifest=" + ("false".equals(withManifest) ? "false" : "true"); // path is validated before executing String filepath = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_NAME"), true, false); if (!isValidExportPath(filepath, logFile)) { throw new ParseException(Messages.getInstance() .getString("CommandLineProcessor.ERROR_0005_INVALID_FILE_PATH", filepath)); } initRestService(); WebResource resource = client.resource(exportURL); // Response response Builder builder = resource.type(MediaType.MULTIPART_FORM_DATA).accept(MediaType.TEXT_HTML_TYPE); ClientResponse response = builder.get(ClientResponse.class); if (response != null && response.getStatus() == 200) { String filename = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_FILEPATH_NAME"), true, false); final InputStream input = response.getEntityInputStream(); createZipFile(filename, input); input.close(); String message = Messages.getInstance().getString("CommandLineProcessor.INFO_EXPORT_COMPLETED") .concat("\n"); message += Messages.getInstance().getString("CommandLineProcessor.INFO_RESPONSE_STATUS", response.getStatus()); message += "\n"; message += Messages.getInstance().getString("CommandLineProcessor.INFO_EXPORT_WRITTEN_TO", filename); if (logFile != null && !"".equals(logFile)) { System.out.println(message); writeFile(message, logFile); } } else { System.out.println( Messages.getInstance().getErrorString("CommandLineProcessor.ERROR_0002_INVALID_RESPONSE")); if (response != null && response.getStatus() == 404) { throw new ParseException(Messages.getInstance() .getErrorString("CommandLineProcessor.ERROR_0004_UNKNOWN_SOURCE", path)); } } } private boolean isValidExportPath(String filePath, String logFile) { boolean isValid = false; if (filePath != null && filePath.toLowerCase().endsWith(".zip")) { int fileNameIdx = filePath.replace("\\", "/").lastIndexOf("/"); if (fileNameIdx >= 0) { String directoryPath = filePath.substring(0, fileNameIdx); File f = new File(directoryPath); if (f != null && f.exists() && f.isDirectory()) { isValid = true; } } } if (!isValid && logFile != null && !"".equals(logFile)) { writeFile("Invalid file-path:" + filePath, logFile); } return isValid; } /** * create the zip file from the input stream * * @param filename * @param input * InputStream */ private void createZipFile(String filename, final InputStream input) { OutputStream output = null; try { output = new FileOutputStream(filename); byte[] buffer = new byte[8 * 1024]; int bytesRead; while ((bytesRead = input.read(buffer)) != -1) { output.write(buffer, 0, bytesRead); } buffer = null; } catch (IOException e) { e.printStackTrace(); } finally { if (output != null) { try { output.close(); } catch (Exception e) { e.printStackTrace(); } } } } public synchronized void setRepository(final IUnifiedRepository repository) { if (repository == null) { throw new IllegalArgumentException(); } this.repository = repository; } /** * Why does this return a web service? Going directly to the IUnifiedRepository requires the following: * <p/> * <ul> * <li>PentahoSessionHolder setup including password and tenant ID. (The server doesn't even process passwords today-- * it assumes that Spring Security processed it. This would require code changes.)</li> * <li>User must specify path to Jackrabbit files (i.e. system/jackrabbit).</li> * </ul> */ protected synchronized IUnifiedRepository getRepository() throws ParseException { if (repository != null) { return repository; } final String NAMESPACE_URI = "http://www.pentaho.org/ws/1.0"; //$NON-NLS-1$ final String SERVICE_NAME = "unifiedRepository"; //$NON-NLS-1$ String urlString = getOptionValue( Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_URL_NAME"), true, false).trim(); if (urlString.endsWith("/")) { urlString = urlString.substring(0, urlString.length() - 1); } urlString = urlString + "/webservices/" + SERVICE_NAME + "?wsdl"; URL url; try { url = new URL(urlString); } catch (MalformedURLException e) { throw new IllegalArgumentException(e); } Service service = Service.create(url, new QName(NAMESPACE_URI, SERVICE_NAME)); IUnifiedRepositoryJaxwsWebService port = service.getPort(IUnifiedRepositoryJaxwsWebService.class); // http basic authentication ((BindingProvider) port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, getOptionValue(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_USERNAME_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_USERNAME_NAME"), true, false)); ((BindingProvider) port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, getOptionValue(Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PASSWORD_KEY"), Messages.getInstance().getString("CommandLineProcessor.INFO_OPTION_PASSWORD_NAME"), true, true)); // accept cookies to maintain session on server ((BindingProvider) port).getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true); // support streaming binary data // TODO mlowery this is not portable between JAX-WS implementations // (uses com.sun) ((BindingProvider) port).getRequestContext().put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192); SOAPBinding binding = (SOAPBinding) ((BindingProvider) port).getBinding(); binding.setMTOMEnabled(true); final UnifiedRepositoryToWebServiceAdapter unifiedRepositoryToWebServiceAdapter = new UnifiedRepositoryToWebServiceAdapter( port); repository = unifiedRepositoryToWebServiceAdapter; return unifiedRepositoryToWebServiceAdapter; } /** * Returns the option value from the command line * * @param option * the option whose value should be returned (NOTE: {@code null} will be returned if the option was not * provided) * @param required * indicates if the option is required * @param emptyOk * indicates if a blank value is acceptable * @return the value provided from the command line, or {@code null} if none was provided * @throws ParseException * indicates the required or non-blank value was not provided */ protected String getOptionValue(final String option, final boolean required, final boolean emptyOk) throws ParseException { final String value = StringUtils.trim(commandLine.getOptionValue(option)); if (required && StringUtils.isEmpty(value)) { throw new ParseException( Messages.getInstance().getErrorString("CommandLineProcessor.ERROR_0001_MISSING_ARG", option)); } if (!emptyOk && StringUtils.isEmpty(value)) { throw new ParseException( Messages.getInstance().getErrorString("CommandLineProcessor.ERROR_0001_MISSING_ARG", option)); } return value; } /** * Returns the option value from the command line * * @param shortOption * the single character option whose value should be returned (NOTE: {@code null} will be returned if the * option was not provided) * @param longOption * the string option whose value should be returned (NOTE: {@code null} will be returned if the option was * not provided) * @param required * indicates if the option is required * @param emptyOk * indicates if a blank value is acceptable * @return the value provided from the command line, or {@code null} if none was provided * @throws ParseException * indicates the required or non-blank value was not provided */ protected String getOptionValue(final String shortOption, final String longOption, final boolean required, final boolean emptyOk) throws ParseException { // first try the short option parameter String value = StringUtils.trim(commandLine.getOptionValue(shortOption)); if (StringUtils.isEmpty(value)) { // if its empty, try the long option value = StringUtils.trim(commandLine.getOptionValue(longOption)); } if (required && StringUtils.isEmpty(value)) { throw new ParseException(Messages.getInstance() .getErrorString("CommandLineProcessor.ERROR_0001_MISSING_ARG", longOption)); } if (!emptyOk && StringUtils.isEmpty(value)) { throw new ParseException(Messages.getInstance() .getErrorString("CommandLineProcessor.ERROR_0001_MISSING_ARG", longOption)); } return value; } /** * internal helper to write output file * * @param message * @param logFile */ private void writeFile(String message, String logFile) { try { File file = new File(logFile); FileOutputStream fout = FileUtils.openOutputStream(file); IOUtils.copy(IOUtils.toInputStream(message), fout); fout.close(); } catch (Exception ex) { ex.printStackTrace(); } } /** * */ protected static void printHelp() { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp(Messages.getInstance().getString("CommandLineProcessor.INFO_PRINTHELP_CMDLINE"), Messages.getInstance().getString("CommandLineProcessor.INFO_PRINTHELP_HEADER"), options, Messages.getInstance().getString("CommandLineProcessor.INFO_PRINTHELP_FOOTER")); } }