| /******************************************************************************* |
| * 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.ofbiz.entityext.data; |
| |
| import java.net.URL; |
| import java.net.MalformedURLException; |
| import java.text.NumberFormat; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.TreeSet; |
| import java.io.File; |
| |
| import javolution.util.FastList; |
| |
| import org.ofbiz.base.container.Container; |
| import org.ofbiz.base.container.ContainerConfig; |
| import org.ofbiz.base.container.ContainerException; |
| import org.ofbiz.base.util.Debug; |
| import org.ofbiz.base.util.StringUtil; |
| import org.ofbiz.base.util.UtilURL; |
| import org.ofbiz.base.util.UtilValidate; |
| import org.ofbiz.entity.DelegatorFactory; |
| import org.ofbiz.entity.GenericDelegator; |
| import org.ofbiz.entity.GenericEntityException; |
| import org.ofbiz.entity.jdbc.DatabaseUtil; |
| import org.ofbiz.entity.model.ModelEntity; |
| import org.ofbiz.entity.util.EntityDataLoader; |
| import org.ofbiz.service.ServiceDispatcher; |
| import org.ofbiz.service.ThreadContext; |
| |
| |
| /** |
| * Some utility routines for loading seed data. |
| */ |
| public class EntityDataLoadContainer implements Container { |
| |
| public static final String module = EntityDataLoadContainer.class.getName(); |
| |
| protected String overrideDelegator = null; |
| protected String overrideGroup = null; |
| protected String configFile = null; |
| protected String readers = null; |
| protected String directory = null; |
| protected List<String> files = FastList.newInstance(); |
| protected String component = null; |
| protected boolean useDummyFks = false; |
| protected boolean maintainTxs = false; |
| protected boolean tryInserts = false; |
| protected boolean repairColumns = false; |
| protected boolean dropPks = false; |
| protected boolean createPks = false; |
| protected boolean dropConstraints = false; |
| protected boolean createConstraints = false; |
| protected int txTimeout = -1; |
| |
| public EntityDataLoadContainer() { |
| super(); |
| } |
| |
| /** |
| * @see org.ofbiz.base.container.Container#init(java.lang.String[], java.lang.String) |
| */ |
| public void init(String[] args, String configFile) throws ContainerException { |
| this.configFile = configFile; |
| // disable job scheduler, JMS listener and startup services |
| ServiceDispatcher.enableJM(false); |
| ServiceDispatcher.enableJMS(false); |
| ServiceDispatcher.enableSvcs(false); |
| |
| /* |
| install arguments: |
| readers (none, all, seed, demo, ext, etc - configured in entityengine.xml and associated via ofbiz-component.xml) |
| timeout (transaction timeout default 7200) |
| delegator (overrides the delegator name configured for the container) |
| group (overrides the entity group name configured for the container) |
| dir (imports all XML files in a directory) |
| file (import a specific XML file) |
| |
| Example: |
| $ java -jar ofbiz.jar -install -readers=seed,demo,ext -timeout=7200 -delegator=default -group=org.ofbiz |
| $ java -jar ofbiz.jar -install -file=/tmp/dataload.xml |
| */ |
| if (args != null) { |
| for (String argument: args) { |
| // arguments can prefix w/ a '-'. Just strip them off |
| if (argument.startsWith("-")) { |
| int subIdx = 1; |
| if (argument.startsWith("--")) { |
| subIdx = 2; |
| } |
| argument = argument.substring(subIdx); |
| } |
| |
| // parse the arguments |
| String argumentName; |
| String argumentVal; |
| if (argument.indexOf("=") != -1) { |
| argumentName = argument.substring(0, argument.indexOf("=")); |
| argumentVal = argument.substring(argument.indexOf("=") + 1); |
| } else { |
| argumentName = argument; |
| argumentVal = ""; |
| } |
| Debug.log("Install Argument - " + argumentName + " = " + argumentVal, module); |
| |
| if ("readers".equalsIgnoreCase(argumentName)) { |
| this.readers = argumentVal; |
| } else if ("timeout".equalsIgnoreCase(argumentName)) { |
| try { |
| this.txTimeout = Integer.parseInt(argumentVal); |
| } catch (Exception e) { |
| this.txTimeout = -1; |
| } |
| } else if ("component".equalsIgnoreCase(argumentName)) { |
| this.component = argumentVal; |
| } else if ("delegator".equalsIgnoreCase(argumentName)) { |
| this.overrideDelegator = argumentVal; |
| } else if ("group".equalsIgnoreCase(argumentName)) { |
| this.overrideGroup = argumentVal; |
| } else if ("file".equalsIgnoreCase(argumentName)) { |
| this.files.addAll(StringUtil.split(argumentVal, ",")); |
| } else if ("dir".equalsIgnoreCase(argumentName)) { |
| this.directory = argumentVal; |
| } else if ("createfks".equalsIgnoreCase(argumentName)) { |
| this.useDummyFks = "true".equalsIgnoreCase(argumentVal); |
| } else if ("maintainTxs".equalsIgnoreCase(argumentName)) { |
| this.maintainTxs = "true".equalsIgnoreCase(argumentVal); |
| } else if ("inserts".equalsIgnoreCase(argumentName)) { |
| this.tryInserts = "true".equalsIgnoreCase(argumentVal); |
| } else if ("repair-columns".equalsIgnoreCase(argumentName)) { |
| if (UtilValidate.isEmpty(argumentVal) || "true".equalsIgnoreCase(argumentVal)) { |
| repairColumns = true; |
| } |
| } else if ("drop-pks".equalsIgnoreCase(argumentName)) { |
| if (UtilValidate.isEmpty(argumentVal) || "true".equalsIgnoreCase(argumentVal)) { |
| dropPks = true; |
| } |
| } else if ("create-pks".equalsIgnoreCase(argumentName)) { |
| if (UtilValidate.isEmpty(argumentVal) || "true".equalsIgnoreCase(argumentVal)) { |
| createPks = true; |
| } |
| } else if ("drop-constraints".equalsIgnoreCase(argumentName)) { |
| if (UtilValidate.isEmpty(argumentVal) || "true".equalsIgnoreCase(argumentVal)) { |
| dropConstraints = true; |
| } |
| } else if ("create-constraints".equalsIgnoreCase(argumentName)) { |
| if (UtilValidate.isEmpty(argumentVal) || "true".equalsIgnoreCase(argumentVal)) { |
| createConstraints = true; |
| } |
| } else if ("help".equalsIgnoreCase(argumentName)) { |
| Debug.log("--------------------------------------", module); |
| Debug.log("java -jar ofbiz.jar -install [options]", module); |
| Debug.log("-component=[name] .... only load from a specific component"); |
| Debug.log("-delegator=[name] .... use the defined delegator (default-no-eca", module); |
| Debug.log("-group=[name] ........ override the entity group (org.ofbiz)", module); |
| Debug.log("-file=[path] ......... load a single from from location", module); |
| Debug.log("-createfks ........... create dummy (placeholder) FKs", module); |
| Debug.log("-maintainTxs ......... maintain timestamps in data file", module); |
| Debug.log("-inserts ............. use mostly inserts option", module); |
| Debug.log("-repair-columns ........... repair column sizes", module); |
| Debug.log("-drop-pks ............ drop primary keys", module); |
| Debug.log("-create-pks .......... create primary keys", module); |
| Debug.log("-drop-constraints..... drop indexes and foreign keys before loading", module); |
| Debug.log("-create-constraints... create indexes and foreign keys after loading (default is true w/ drop-constraints)", module); |
| Debug.log("-help ................ display this information", module); |
| System.exit(1); |
| } |
| |
| // special case |
| if (this.readers == null && (!this.files.isEmpty() || this.directory != null)) { |
| this.readers = "none"; |
| } |
| } |
| } |
| } |
| |
| /** |
| * @see org.ofbiz.base.container.Container#start() |
| */ |
| public boolean start() throws ContainerException { |
| ContainerConfig.Container cfg = ContainerConfig.getContainer("dataload-container", configFile); |
| ContainerConfig.Container.Property delegatorNameProp = cfg.getProperty("delegator-name"); |
| ContainerConfig.Container.Property entityGroupNameProp = cfg.getProperty("entity-group-name"); |
| |
| String delegatorName = null; |
| String entityGroupName = null; |
| |
| if (delegatorNameProp == null || delegatorNameProp.value == null || delegatorNameProp.value.length() == 0) { |
| throw new ContainerException("Invalid delegator-name defined in container configuration"); |
| } else { |
| delegatorName = delegatorNameProp.value; |
| } |
| |
| if (entityGroupNameProp == null || entityGroupNameProp.value == null || entityGroupNameProp.value.length() == 0) { |
| throw new ContainerException("Invalid entity-group-name defined in container configuration"); |
| } else { |
| entityGroupName = entityGroupNameProp.value; |
| } |
| |
| // parse the pass in list of readers to use |
| List<String> readerNames = null; |
| if (this.readers != null && !"none".equalsIgnoreCase(this.readers)) { |
| if (this.readers.indexOf(",") == -1) { |
| readerNames = FastList.newInstance(); |
| readerNames.add(this.readers); |
| } else { |
| readerNames = StringUtil.split(this.readers, ","); |
| } |
| } |
| |
| String delegatorNameToUse = overrideDelegator != null ? overrideDelegator : delegatorName; |
| String groupNameToUse = overrideGroup != null ? overrideGroup : entityGroupName; |
| GenericDelegator delegator = DelegatorFactory.getGenericDelegator(delegatorNameToUse); |
| if (delegator == null) { |
| throw new ContainerException("Invalid delegator name!"); |
| } |
| |
| String helperName = delegator.getGroupHelperName(groupNameToUse); |
| if (helperName == null) { |
| throw new ContainerException("Unable to locate the datasource helper for the group [" + groupNameToUse + "]"); |
| } |
| |
| // get the database util object |
| DatabaseUtil dbUtil = new DatabaseUtil(helperName); |
| Map<String, ModelEntity> modelEntities; |
| try { |
| modelEntities = delegator.getModelEntityMapByGroup(groupNameToUse); |
| } catch (GenericEntityException e) { |
| throw new ContainerException(e.getMessage(), e); |
| } |
| TreeSet<String> modelEntityNames = new TreeSet<String>(modelEntities.keySet()); |
| |
| // Set up the execution context |
| ThreadContext.runUnprotected(); |
| ThreadContext.setDelegator(delegator); |
| ThreadContext.pushExecutionArtifact(module, "EntityDataLoad"); |
| try { |
| // check for drop index/fks |
| if (dropConstraints) { |
| List<String> messages = FastList.newInstance(); |
| |
| Debug.logImportant("Dropping foreign key indcies...", module); |
| for (String entityName : modelEntityNames) { |
| ModelEntity modelEntity = modelEntities.get(entityName); |
| if (modelEntity != null) { |
| dbUtil.deleteForeignKeyIndices(modelEntity, messages); |
| } |
| } |
| |
| Debug.logImportant("Dropping declared indices...", module); |
| for (String entityName : modelEntityNames) { |
| ModelEntity modelEntity = modelEntities.get(entityName); |
| if (modelEntity != null) { |
| dbUtil.deleteDeclaredIndices(modelEntity, messages); |
| } |
| } |
| |
| Debug.logImportant("Dropping foreign keys...", module); |
| for (String entityName : modelEntityNames) { |
| ModelEntity modelEntity = modelEntities.get(entityName); |
| if (modelEntity != null) { |
| dbUtil.deleteForeignKeys(modelEntity, modelEntities, messages); |
| } |
| } |
| |
| if (messages.size() > 0) { |
| if (Debug.infoOn()) { |
| for (String message : messages) { |
| Debug.logInfo(message, module); |
| } |
| } |
| } |
| } |
| |
| // drop pks |
| if (dropPks) { |
| List<String> messages = FastList.newInstance(); |
| Debug.logImportant("Dropping primary keys...", module); |
| for (String entityName : modelEntityNames) { |
| ModelEntity modelEntity = modelEntities.get(entityName); |
| if (modelEntity != null) { |
| dbUtil.deletePrimaryKey(modelEntity, messages); |
| } |
| } |
| |
| if (messages.size() > 0) { |
| if (Debug.infoOn()) { |
| for (String message : messages) { |
| Debug.logInfo(message, module); |
| } |
| } |
| } |
| } |
| |
| // repair columns |
| if (repairColumns) { |
| List<String> fieldsToRepair = FastList.newInstance(); |
| List<String> messages = FastList.newInstance(); |
| dbUtil.checkDb(modelEntities, fieldsToRepair, messages, false, false, false, false); |
| if (fieldsToRepair.size() > 0) { |
| messages = FastList.newInstance(); |
| dbUtil.repairColumnSizeChanges(modelEntities, fieldsToRepair, messages); |
| if (messages.size() > 0) { |
| if (Debug.infoOn()) { |
| for (String message : messages) { |
| Debug.logInfo(message, module); |
| } |
| } |
| } |
| } |
| } |
| |
| // get the reader name URLs first |
| List<URL> urlList = null; |
| if (readerNames != null) { |
| urlList = EntityDataLoader.getUrlList(helperName, component, readerNames); |
| } else if (!"none".equalsIgnoreCase(this.readers)) { |
| urlList = EntityDataLoader.getUrlList(helperName, component); |
| } |
| |
| // need a list if it is empty |
| if (urlList == null) { |
| urlList = FastList.newInstance(); |
| } |
| |
| // add in the defined extra files |
| for (String fileName: this.files) { |
| URL fileUrl = UtilURL.fromResource((String) fileName); |
| if (fileUrl != null) { |
| urlList.add(fileUrl); |
| } |
| } |
| |
| // next check for a directory of files |
| if (this.directory != null) { |
| File dir = new File(this.directory); |
| if (dir.exists() && dir.isDirectory() && dir.canRead()) { |
| File[] fileArray = dir.listFiles(); |
| if (fileArray != null && fileArray.length > 0) { |
| for (File file: fileArray) { |
| if (file.getName().toLowerCase().endsWith(".xml")) { |
| try { |
| urlList.add(file.toURI().toURL()); |
| } catch (MalformedURLException e) { |
| Debug.logError(e, "Unable to load file (" + file.getName() + "); not a valid URL.", module); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| // process the list of files |
| NumberFormat changedFormat = NumberFormat.getIntegerInstance(); |
| changedFormat.setMinimumIntegerDigits(5); |
| changedFormat.setGroupingUsed(false); |
| |
| List<Object> errorMessages = FastList.newInstance(); |
| List<String> infoMessages = FastList.newInstance(); |
| int totalRowsChanged = 0; |
| if (UtilValidate.isNotEmpty(urlList)) { |
| Debug.logImportant("=-=-=-=-=-=-= Doing a data load with the following files:", module); |
| for (URL dataUrl: urlList) { |
| Debug.logImportant(dataUrl.toExternalForm(), module); |
| } |
| |
| Debug.logImportant("=-=-=-=-=-=-= Starting the data load...", module); |
| |
| for (URL dataUrl: urlList) { |
| try { |
| int rowsChanged = EntityDataLoader.loadData(dataUrl, helperName, delegator, errorMessages, txTimeout, useDummyFks, maintainTxs, tryInserts); |
| totalRowsChanged += rowsChanged; |
| infoMessages.add(changedFormat.format(rowsChanged) + " of " + changedFormat.format(totalRowsChanged) + " from " + dataUrl.toExternalForm()); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Error loading data file: " + dataUrl.toExternalForm(), module); |
| } |
| } |
| } else { |
| Debug.logImportant("=-=-=-=-=-=-= No data load files found.", module); |
| } |
| |
| if (infoMessages.size() > 0) { |
| Debug.logImportant("=-=-=-=-=-=-= Here is a summary of the data load:", module); |
| for (String message: infoMessages) { |
| Debug.logImportant(message, module); |
| } |
| } |
| |
| if (errorMessages.size() > 0) { |
| Debug.logImportant("The following errors occured in the data load:", module); |
| for (Object message: errorMessages) { |
| Debug.logImportant(message.toString(), module); |
| } |
| } |
| |
| Debug.logImportant("=-=-=-=-=-=-= Finished the data load with " + totalRowsChanged + " rows changed.", module); |
| |
| // create primary keys |
| if (createPks) { |
| List<String> messages = FastList.newInstance(); |
| |
| Debug.logImportant("Creating primary keys...", module); |
| for (String entityName : modelEntityNames) { |
| ModelEntity modelEntity = modelEntities.get(entityName); |
| if (modelEntity != null) { |
| dbUtil.createPrimaryKey(modelEntity, messages); |
| } |
| } |
| if (messages.size() > 0) { |
| if (Debug.infoOn()) { |
| for (String message : messages) { |
| Debug.logInfo(message, module); |
| } |
| } |
| } |
| } |
| |
| // create constraints |
| if (createConstraints) { |
| List<String> messages = FastList.newInstance(); |
| |
| Debug.logImportant("Creating foreign keys...", module); |
| for (String entityName : modelEntityNames) { |
| ModelEntity modelEntity = modelEntities.get(entityName); |
| if (modelEntity != null) { |
| dbUtil.createForeignKeys(modelEntity, modelEntities, messages); |
| } |
| } |
| |
| Debug.logImportant("Creating foreign key indcies...", module); |
| for (String entityName : modelEntityNames) { |
| ModelEntity modelEntity = modelEntities.get(entityName); |
| if (modelEntity != null) { |
| dbUtil.createForeignKeyIndices(modelEntity, messages); |
| } |
| } |
| |
| Debug.logImportant("Creating declared indices...", module); |
| for (String entityName : modelEntityNames) { |
| ModelEntity modelEntity = modelEntities.get(entityName); |
| if (modelEntity != null) { |
| dbUtil.createDeclaredIndices(modelEntity, messages); |
| } |
| } |
| |
| if (messages.size() > 0) { |
| if (Debug.infoOn()) { |
| for (String message : messages) { |
| Debug.logInfo(message, module); |
| } |
| } |
| } |
| } |
| } finally { |
| ThreadContext.popExecutionArtifact(); |
| ThreadContext.endRunUnprotected(); |
| } |
| return true; |
| } |
| |
| /** |
| * @see org.ofbiz.base.container.Container#stop() |
| */ |
| public void stop() throws ContainerException { |
| } |
| } |