/* * 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.ofbiz.webtools; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.sql.Timestamp; import java.text.NumberFormat; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import java.util.Set; import java.util.TreeSet; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.ofbiz.base.location.FlexibleLocation; import org.apache.ofbiz.base.util.Debug; import org.apache.ofbiz.base.util.GeneralException; import org.apache.ofbiz.base.util.StringUtil; import org.apache.ofbiz.base.util.UtilDateTime; import org.apache.ofbiz.base.util.UtilGenerics; import org.apache.ofbiz.base.util.UtilMisc; import org.apache.ofbiz.base.util.UtilPlist; import org.apache.ofbiz.base.util.UtilProperties; import org.apache.ofbiz.base.util.UtilProperties.UtilResourceBundle; import org.apache.ofbiz.base.util.UtilURL; import org.apache.ofbiz.base.util.UtilValidate; import org.apache.ofbiz.base.util.template.FreeMarkerWorker; import org.apache.ofbiz.entity.Delegator; import org.apache.ofbiz.entity.DelegatorFactory; import org.apache.ofbiz.entity.GenericEntityException; import org.apache.ofbiz.entity.GenericValue; import org.apache.ofbiz.entity.condition.EntityCondition; import org.apache.ofbiz.entity.condition.EntityOperator; import org.apache.ofbiz.entity.model.ModelEntity; import org.apache.ofbiz.entity.model.ModelField; import org.apache.ofbiz.entity.model.ModelFieldType; import org.apache.ofbiz.entity.model.ModelIndex; import org.apache.ofbiz.entity.model.ModelKeyMap; import org.apache.ofbiz.entity.model.ModelReader; import org.apache.ofbiz.entity.model.ModelRelation; import org.apache.ofbiz.entity.model.ModelUtil; import org.apache.ofbiz.entity.model.ModelViewEntity; import org.apache.ofbiz.entity.transaction.TransactionUtil; import org.apache.ofbiz.entity.util.EntityDataAssert; import org.apache.ofbiz.entity.util.EntityDataLoader; import org.apache.ofbiz.entity.util.EntityListIterator; import org.apache.ofbiz.entity.util.EntityQuery; import org.apache.ofbiz.entity.util.EntitySaxReader; import org.apache.ofbiz.entityext.EntityGroupUtil; import org.apache.ofbiz.security.Security; import org.apache.ofbiz.service.DispatchContext; import org.apache.ofbiz.service.LocalDispatcher; import org.apache.ofbiz.service.GenericServiceException; import org.apache.ofbiz.service.ServiceUtil; import org.apache.ofbiz.webtools.artifactinfo.ArtifactInfoFactory; import org.apache.ofbiz.webtools.artifactinfo.ServiceArtifactInfo; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * WebTools Services */ public class WebToolsServices { public static final String module = WebToolsServices.class.getName(); public static final String resource = "WebtoolsUiLabels"; public static Map<String, Object> entityImport(DispatchContext dctx, Map<String, ? extends Object> context) { GenericValue userLogin = (GenericValue) context.get("userLogin"); LocalDispatcher dispatcher = dctx.getDispatcher(); Locale locale = (Locale) context.get("locale"); List<String> messages = new LinkedList<String>(); String filename = (String)context.get("filename"); String fmfilename = (String)context.get("fmfilename"); String fulltext = (String)context.get("fulltext"); boolean isUrl = (String)context.get("isUrl") != null; String mostlyInserts = (String)context.get("mostlyInserts"); String maintainTimeStamps = (String)context.get("maintainTimeStamps"); String createDummyFks = (String)context.get("createDummyFks"); String checkDataOnly = (String) context.get("checkDataOnly"); Map<String, Object> placeholderValues = UtilGenerics.checkMap(context.get("placeholderValues")); Integer txTimeout = (Integer)context.get("txTimeout"); if (txTimeout == null) { txTimeout = Integer.valueOf(7200); } URL url = null; // ############################# // The filename to parse is prepared // ############################# if (UtilValidate.isNotEmpty(filename)) { try { url = isUrl?FlexibleLocation.resolveLocation(filename):UtilURL.fromFilename(filename); } catch (MalformedURLException mue) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsInvalidFileName", UtilMisc.toMap("filename", filename, "errorString", mue.getMessage()), locale)); } catch (Exception exc) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsErrorReadingFileName", UtilMisc.toMap("filename", filename, "errorString", exc.getMessage()), locale)); } } // ############################# // FM Template // ############################# if (UtilValidate.isNotEmpty(fmfilename) && (UtilValidate.isNotEmpty(fulltext) || url != null)) { File fmFile = new File(fmfilename); if (!fmFile.exists()) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsErrorReadingTemplateFile", UtilMisc.toMap("filename", fmfilename, "errorString", "Template file not found."), locale)); } try { DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); InputSource ins = url != null ? new InputSource(url.openStream()) : new InputSource(new StringReader(fulltext)); Document doc; try { doc = documentBuilder.parse(ins); } finally { if (ins.getByteStream() != null) { ins.getByteStream().close(); } if (ins.getCharacterStream() != null) { ins.getCharacterStream().close(); } } StringWriter outWriter = new StringWriter(); Map<String, Object> fmcontext = new HashMap<>(); fmcontext.put("doc", doc); FreeMarkerWorker.renderTemplate(fmFile.toURI().toURL().toString(), fmcontext, outWriter); fulltext = outWriter.toString(); } catch (Exception ex) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsErrorProcessingTemplateFile", UtilMisc.toMap("filename", fmfilename, "errorString", ex.getMessage()), locale)); } } // ############################# // The parsing takes place // ############################# if (fulltext != null || url != null) { try { Map<String, Object> inputMap = UtilMisc.toMap("mostlyInserts", mostlyInserts, "createDummyFks", createDummyFks, "checkDataOnly", checkDataOnly, "maintainTimeStamps", maintainTimeStamps, "txTimeout", txTimeout, "placeholderValues", placeholderValues, "userLogin", userLogin); if (fulltext != null) { inputMap.put("xmltext", fulltext); } else { inputMap.put("url", url); } Map<String, Object> outputMap = dispatcher.runSync("parseEntityXmlFile", inputMap); if (ServiceUtil.isError(outputMap)) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsErrorParsingFile", UtilMisc.toMap("errorString", ServiceUtil.getErrorMessage(outputMap)), locale)); } else { Long numberRead = (Long)outputMap.get("rowProcessed"); messages.add(UtilProperties.getMessage(resource, "EntityImportRowProcessed", UtilMisc.toMap("numberRead", numberRead.toString()), locale)); } } catch (GenericServiceException gsex) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "EntityImportParsingError", UtilMisc.toMap("errorString", gsex.getMessage()), locale)); } catch (Exception ex) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "EntityImportParsingError", UtilMisc.toMap("errorString", ex.getMessage()), locale)); } } else { messages.add(UtilProperties.getMessage(resource, "EntityImportNoXmlFileSpecified", locale)); } // send the notification Map<String, Object> resp = UtilMisc.toMap("messages", (Object) messages); return resp; } public static Map<String, Object> entityImportDir(DispatchContext dctx, Map<String, ? extends Object> context) { GenericValue userLogin = (GenericValue) context.get("userLogin"); LocalDispatcher dispatcher = dctx.getDispatcher(); Locale locale = (Locale) context.get("locale"); List<String> messages = new LinkedList<String>(); String path = (String) context.get("path"); String mostlyInserts = (String) context.get("mostlyInserts"); String maintainTimeStamps = (String) context.get("maintainTimeStamps"); String createDummyFks = (String) context.get("createDummyFks"); boolean deleteFiles = (String) context.get("deleteFiles") != null; String checkDataOnly = (String) context.get("checkDataOnly"); Map<String, Object> placeholderValues = UtilGenerics.checkMap(context.get("placeholderValues")); Integer txTimeout = (Integer)context.get("txTimeout"); Long filePause = (Long)context.get("filePause"); if (txTimeout == null) { txTimeout = Integer.valueOf(7200); } if (filePause == null) { filePause = Long.valueOf(0); } if (UtilValidate.isNotEmpty(path)) { long pauseLong = filePause != null ? filePause.longValue() : 0; File baseDir = new File(path); if (baseDir.isDirectory() && baseDir.canRead()) { File[] fileArray = baseDir.listFiles(); List<File> files = new LinkedList<File>(); for (File file: fileArray) { if (file.getName().toUpperCase().endsWith("XML")) { files.add(file); } } int passes=0; int initialListSize = files.size(); int lastUnprocessedFilesCount = 0; List<File> unprocessedFiles = new LinkedList<File>(); while (files.size()>0 && files.size() != lastUnprocessedFilesCount) { lastUnprocessedFilesCount = files.size(); unprocessedFiles = new LinkedList<File>(); for (File f: files) { Map<String, Object> parseEntityXmlFileArgs = UtilMisc.toMap("mostlyInserts", mostlyInserts, "createDummyFks", createDummyFks, "checkDataOnly", checkDataOnly, "maintainTimeStamps", maintainTimeStamps, "txTimeout", txTimeout, "placeholderValues", placeholderValues, "userLogin", userLogin); try { URL furl = f.toURI().toURL(); parseEntityXmlFileArgs.put("url", furl); Map<String, Object> outputMap = dispatcher.runSync("parseEntityXmlFile", parseEntityXmlFileArgs); Long numberRead = (Long) outputMap.get("rowProcessed"); messages.add(UtilProperties.getMessage(resource, "EntityImportNumberOfEntityToBeProcessed", UtilMisc.toMap("numberRead", numberRead.toString(), "fileName", f.getName()), locale)); if (deleteFiles) { messages.add(UtilProperties.getMessage(resource, "EntityImportDeletFile", UtilMisc.toMap("fileName", f.getName()), locale)); f.delete(); } } catch (Exception e) { unprocessedFiles.add(f); messages.add(UtilProperties.getMessage(resource, "EntityImportFailedFile", UtilMisc.toMap("fileName", f.getName()), locale)); } // pause in between files if (pauseLong > 0) { Debug.logInfo("Pausing for [" + pauseLong + "] seconds - " + UtilDateTime.nowTimestamp(), module); try { Thread.sleep((pauseLong * 1000)); } catch (InterruptedException ie) { Debug.logInfo("Pause finished - " + UtilDateTime.nowTimestamp(), module); } } } files = unprocessedFiles; passes++; messages.add(UtilProperties.getMessage(resource, "EntityImportPassedFile", UtilMisc.toMap("passes", passes), locale)); Debug.logInfo("Pass " + passes + " complete", module); } lastUnprocessedFilesCount=unprocessedFiles.size(); messages.add("---------------------------------------"); messages.add(UtilProperties.getMessage(resource, "EntityImportSucceededNumberFile", UtilMisc.toMap("succeeded", (initialListSize-lastUnprocessedFilesCount), "total", initialListSize), locale)); messages.add(UtilProperties.getMessage(resource, "EntityImportFailedNumberFile", UtilMisc.toMap("failed", lastUnprocessedFilesCount, "total", initialListSize), locale)); messages.add("---------------------------------------"); messages.add(UtilProperties.getMessage(resource, "EntityImportFailedFileList", locale)); for (File file: unprocessedFiles) { messages.add(file.toString()); } } else { messages.add(UtilProperties.getMessage(resource, "EntityImportPathNotFound", locale)); } } else { messages.add(UtilProperties.getMessage(resource, "EntityImportPathNotSpecified", locale)); } // send the notification Map<String, Object> resp = UtilMisc.toMap("messages", (Object) messages); return resp; } public static Map<String, Object> entityImportReaders(DispatchContext dctx, Map<String, Object> context) { String readers = (String) context.get("readers"); String overrideDelegator = (String) context.get("overrideDelegator"); String overrideGroup = (String) context.get("overrideGroup"); boolean useDummyFks = "true".equals(context.get("createDummyFks")); boolean maintainTxs = "true".equals(context.get("maintainTimeStamps")); boolean tryInserts = "true".equals(context.get("mostlyInserts")); boolean checkDataOnly = "true".equals(context.get("checkDataOnly")); Locale locale = (Locale) context.get("locale"); Integer txTimeoutInt = (Integer) context.get("txTimeout"); int txTimeout = txTimeoutInt != null ? txTimeoutInt.intValue() : -1; List<Object> messages = new LinkedList<Object>(); // parse the pass in list of readers to use List<String> readerNames = null; if (UtilValidate.isNotEmpty(readers) && !"none".equalsIgnoreCase(readers)) { if (readers.indexOf(",") == -1) { readerNames = new LinkedList<String>(); readerNames.add(readers); } else { readerNames = StringUtil.split(readers, ","); } } String groupNameToUse = overrideGroup != null ? overrideGroup : "org.apache.ofbiz"; Delegator delegator = null; if (UtilValidate.isNotEmpty(overrideDelegator)) { delegator = DelegatorFactory.getDelegator(overrideDelegator); } else { delegator = dctx.getDelegator(); } String helperName = delegator.getGroupHelperName(groupNameToUse); if (helperName == null) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "EntityImportNoDataSourceSpecified", UtilMisc.toMap("groupNameToUse", groupNameToUse), locale)); } // get the reader name URLs first List<URL> urlList = null; if (readerNames != null) { urlList = EntityDataLoader.getUrlList(helperName, readerNames); } else if (!"none".equalsIgnoreCase(readers)) { urlList = EntityDataLoader.getUrlList(helperName); } // need a list if it is empty if (urlList == null) { urlList = new LinkedList<URL>(); } // process the list of files NumberFormat changedFormat = NumberFormat.getIntegerInstance(); changedFormat.setMinimumIntegerDigits(5); changedFormat.setGroupingUsed(false); List<Object> errorMessages = new LinkedList<Object>(); List<String> infoMessages = new LinkedList<String>(); int totalRowsChanged = 0; if (UtilValidate.isNotEmpty(urlList)) { messages.add("=-=-=-=-=-=-= Doing a data " + (checkDataOnly ? "check" : "load") + " with the following files:"); for (URL dataUrl: urlList) { messages.add(dataUrl.toExternalForm()); } messages.add("=-=-=-=-=-=-= Starting the data " + (checkDataOnly ? "check" : "load") + "..."); for (URL dataUrl: urlList) { try { int rowsChanged = 0; if (checkDataOnly) { try { errorMessages.add("Checking data in [" + dataUrl.toExternalForm() + "]"); rowsChanged = EntityDataAssert.assertData(dataUrl, delegator, errorMessages); } catch (SAXException e) { errorMessages.add("Error checking data in [" + dataUrl.toExternalForm() + "]: " + e.toString()); } catch (ParserConfigurationException e) { errorMessages.add("Error checking data in [" + dataUrl.toExternalForm() + "]: " + e.toString()); } catch (IOException e) { errorMessages.add("Error checking data in [" + dataUrl.toExternalForm() + "]: " + e.toString()); } } else { 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 { messages.add("=-=-=-=-=-=-= No data " + (checkDataOnly ? "check" : "load") + " files found."); } if (infoMessages.size() > 0) { messages.add("=-=-=-=-=-=-= Here is a summary of the data " + (checkDataOnly ? "check" : "load") + ":"); messages.addAll(infoMessages); } if (errorMessages.size() > 0) { messages.add("=-=-=-=-=-=-= The following errors occurred in the data " + (checkDataOnly ? "check" : "load") + ":"); messages.addAll(errorMessages); } messages.add("=-=-=-=-=-=-= Finished the data " + (checkDataOnly ? "check" : "load") + " with " + totalRowsChanged + " rows " + (checkDataOnly ? "checked" : "changed") + "."); Map<String, Object> resultMap = ServiceUtil.returnSuccess(); resultMap.put("messages", messages); return resultMap; } public static Map<String, Object> parseEntityXmlFile(DispatchContext dctx, Map<String, ? extends Object> context) { Delegator delegator = dctx.getDelegator(); Locale locale = (Locale) context.get("locale"); URL url = (URL) context.get("url"); String xmltext = (String) context.get("xmltext"); if (url == null && xmltext == null) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "EntityImportNoXmlFileOrTextSpecified", locale)); } boolean mostlyInserts = (String) context.get("mostlyInserts") != null; boolean maintainTimeStamps = (String) context.get("maintainTimeStamps") != null; boolean createDummyFks = (String) context.get("createDummyFks") != null; boolean checkDataOnly = (String) context.get("checkDataOnly") != null; Integer txTimeout = (Integer) context.get("txTimeout"); Map<String, Object> placeholderValues = UtilGenerics.checkMap(context.get("placeholderValues")); if (txTimeout == null) { txTimeout = Integer.valueOf(7200); } long rowProcessed = 0; try { EntitySaxReader reader = new EntitySaxReader(delegator); reader.setUseTryInsertMethod(mostlyInserts); reader.setMaintainTxStamps(maintainTimeStamps); reader.setTransactionTimeout(txTimeout.intValue()); reader.setCreateDummyFks(createDummyFks); reader.setCheckDataOnly(checkDataOnly); reader.setPlaceholderValues(placeholderValues); long numberRead = (url != null ? reader.parse(url) : reader.parse(xmltext)); rowProcessed = numberRead; } catch (Exception ex) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "EntityImportParsingError", UtilMisc.toMap("errorString", ex.toString()), locale)); } // send the notification Map<String, Object> resp = UtilMisc.<String, Object>toMap("rowProcessed", rowProcessed); return resp; } public static Map<String, Object> entityExportAll(DispatchContext dctx, Map<String, ? extends Object> context) { Delegator delegator = dctx.getDelegator(); Locale locale = (Locale) context.get("locale"); String outpath = (String)context.get("outpath"); // mandatory Timestamp fromDate = (Timestamp)context.get("fromDate"); Integer txTimeout = (Integer)context.get("txTimeout"); if (txTimeout == null) { txTimeout = Integer.valueOf(7200); } List<String> results = new LinkedList<String>(); if (UtilValidate.isNotEmpty(outpath)) { File outdir = new File(outpath); if (!outdir.exists()) { outdir.mkdir(); } if (outdir.isDirectory() && outdir.canWrite()) { Set<String> passedEntityNames; try { ModelReader reader = delegator.getModelReader(); Collection<String> ec = reader.getEntityNames(); passedEntityNames = new TreeSet<String>(ec); } catch (Exception exc) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "EntityImportErrorRetrievingEntityNames", locale)); } int fileNumber = 1; for (String curEntityName: passedEntityNames) { long numberWritten = 0; EntityListIterator values = null; try { ModelEntity me = delegator.getModelEntity(curEntityName); if (me instanceof ModelViewEntity) { results.add("["+fileNumber +"] [vvv] " + curEntityName + " skipping view entity"); continue; } boolean beganTx = TransactionUtil.begin(); // some databases don't support cursors, or other problems may happen, so if there is an error here log it and move on to get as much as possible try { List<EntityCondition> conds = new LinkedList<EntityCondition>(); if (UtilValidate.isNotEmpty(fromDate)) { conds.add(EntityCondition.makeCondition("createdStamp", EntityOperator.GREATER_THAN_EQUAL_TO, fromDate)); } values = EntityQuery.use(delegator).from(curEntityName).where(conds).orderBy(me.getPkFieldNames()).queryIterator(); } catch (Exception entityEx) { results.add("["+fileNumber +"] [xxx] Error when writing " + curEntityName + ": " + entityEx); continue; } //Don't bother writing the file if there's nothing //to put into it GenericValue value = values.next(); if (value != null) { PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(outdir, curEntityName +".xml")), "UTF-8"))); writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); writer.println("<entity-engine-xml>"); do { value.writeXmlText(writer, ""); numberWritten++; if (numberWritten % 500 == 0) { TransactionUtil.commit(beganTx); beganTx = TransactionUtil.begin(); } } while ((value = values.next()) != null); writer.println("</entity-engine-xml>"); writer.close(); results.add("["+fileNumber +"] [" + numberWritten + "] " + curEntityName + " wrote " + numberWritten + " records"); } else { results.add("["+fileNumber +"] [---] " + curEntityName + " has no records, not writing file"); } values.close(); TransactionUtil.commit(beganTx); } catch (Exception ex) { if (values != null) { try { values.close(); } catch (Exception exc) { //Debug.warning(); } } results.add("["+fileNumber +"] [xxx] Error when writing " + curEntityName + ": " + ex); } fileNumber++; } } else { results.add("Path not found or no write access."); } } else { results.add("No path specified, doing nothing."); } // send the notification Map<String, Object> resp = UtilMisc.<String, Object>toMap("results", results); return resp; } /** Get entity reference data. Returns the number of entities in * <code>numberOfEntities</code> and a List of Maps - * <code>packagesList</code>. * Each Map contains:<br> * <ul><li><code>packageName</code> - the entity package name</li> * <li><code>entitiesList</code> - a list of Maps: <ul> <li><code>entityName</code></li> <li><code>helperName</code></li> <li><code>groupName</code></li> <li><code>plainTableName</code></li> <li><code>title</code></li> <li><code>description</code></li> <!-- <li><code>location</code></li> --> <li><code>javaNameList</code> - list of Maps: <ul> <li><code>isPk</code></li> <li><code>name</code></li> <li><code>colName</code></li> <li><code>description</code></li> <li><code>type</code></li> <li><code>javaType</code></li> <li><code>sqlType</code></li> </ul> </li> <li><code>relationsList</code> - list of Maps: <ul> <li><code>title</code></li> <!-- <li><code>description</code></li> --> <li><code>relEntity</code></li> <li><code>fkName</code></li> <li><code>type</code></li> <li><code>length</code></li> <li><code>keysList</code> - list of Maps: <ul> <li><code>row</code></li> <li><code>fieldName</code></li> <li><code>relFieldName</code></li> </ul> </li> </ul> </li> <li><code>indexList</code> - list of Maps: <ul> <li><code>name</code></li> <!-- <li><code>description</code></li> --> <li><code>fieldNameList</code> - list of Strings</li> </ul> </li> </ul> </li></ul> * */ public static Map<String, Object> getEntityRefData(DispatchContext dctx, Map<String, ? extends Object> context) { Delegator delegator = dctx.getDelegator(); Locale locale = (Locale) context.get("locale"); ClassLoader loader = Thread.currentThread().getContextClassLoader(); Map<String, Object> resultMap = ServiceUtil.returnSuccess(); ModelReader reader = delegator.getModelReader(); Map<String, TreeSet<String>> entitiesByPackage = new HashMap<String, TreeSet<String>>(); Set<String> packageNames = new TreeSet<String>(); Set<String> tableNames = new TreeSet<String>(); //put the entityNames TreeSets in a HashMap by packageName try { Collection<String> ec = reader.getEntityNames(); resultMap.put("numberOfEntities", ec.size()); for (String eName: ec) { ModelEntity ent = reader.getModelEntity(eName); //make sure the table name is in the list of all table names, if not null if (UtilValidate.isNotEmpty(ent.getPlainTableName())) { tableNames.add(ent.getPlainTableName()); } TreeSet<String> entities = entitiesByPackage.get(ent.getPackageName()); if (entities == null) { entities = new TreeSet<String>(); entitiesByPackage.put(ent.getPackageName(), entities); packageNames.add(ent.getPackageName()); } entities.add(eName); } } catch (GenericEntityException e) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "EntityImportErrorRetrievingEntityNames", locale) + e.getMessage()); } String search = (String) context.get("search"); List<Map<String, Object>> packagesList = new LinkedList<Map<String,Object>>(); try { for (String pName : packageNames) { Map<String, Object> packageMap = new HashMap<String, Object>(); TreeSet<String> entities = entitiesByPackage.get(pName); List<Map<String, Object>> entitiesList = new LinkedList<Map<String,Object>>(); for (String entityName: entities) { Map<String, Object> entityMap = new HashMap<String, Object>(); String helperName = delegator.getEntityHelperName(entityName); String groupName = delegator.getEntityGroupName(entityName); if (search == null || entityName.toLowerCase().indexOf(search.toLowerCase()) != -1) { ModelEntity entity = reader.getModelEntity(entityName); ResourceBundle bundle = null; if (UtilValidate.isNotEmpty(entity.getDefaultResourceName())) { try { bundle = UtilResourceBundle.getBundle(entity.getDefaultResourceName(), locale, loader); } catch (Exception exception) { Debug.logInfo(exception.getMessage(), module); } } String entityDescription = null; if (bundle != null) { try { entityDescription = bundle.getString("EntityDescription." + entity.getEntityName()); } catch (Exception exception) {} } if (UtilValidate.isEmpty(entityDescription)) { entityDescription = entity.getDescription(); } // fields list List<Map<String, Object>> javaNameList = new LinkedList<Map<String,Object>>(); for (Iterator<ModelField> f = entity.getFieldsIterator(); f.hasNext();) { Map<String, Object> javaNameMap = new HashMap<String, Object>(); ModelField field = f.next(); ModelFieldType type = delegator.getEntityFieldType(entity, field.getType()); javaNameMap.put("isPk", field.getIsPk()); javaNameMap.put("name", field.getName()); javaNameMap.put("colName", field.getColName()); String fieldDescription = null; if (bundle != null) { try { fieldDescription = bundle.getString("FieldDescription." + entity.getEntityName() + "." + field.getName()); } catch (Exception exception) {} } if (UtilValidate.isEmpty(fieldDescription)) { fieldDescription = field.getDescription(); } if (UtilValidate.isEmpty(fieldDescription) && bundle != null) { try { fieldDescription = bundle.getString("FieldDescription." + field.getName()); } catch (Exception exception) {} } if (UtilValidate.isEmpty(fieldDescription)) { fieldDescription = ModelUtil.javaNameToDbName(field.getName()).toLowerCase(); fieldDescription = ModelUtil.upperFirstChar(fieldDescription.replace('_', ' ')); } javaNameMap.put("description", fieldDescription); javaNameMap.put("type", (field.getType()) != null ? field.getType() : null); javaNameMap.put("javaType", (field.getType() != null && type != null) ? type.getJavaType() : "Undefined"); javaNameMap.put("sqlType", (type != null && type.getSqlType() != null) ? type.getSqlType() : "Undefined"); javaNameMap.put("encrypted", field.getEncryptMethod().isEncrypted()); javaNameMap.put("encryptMethod", field.getEncryptMethod()); javaNameList.add(javaNameMap); } // relations list List<Map<String, Object>> relationsList = new LinkedList<Map<String,Object>>(); for (int r = 0; r < entity.getRelationsSize(); r++) { Map<String, Object> relationMap = new HashMap<String, Object>(); ModelRelation relation = entity.getRelation(r); List<Map<String, Object>> keysList = new LinkedList<Map<String,Object>>(); int row = 1; for (ModelKeyMap keyMap : relation.getKeyMaps()) { Map<String, Object> keysMap = new HashMap<String, Object>(); String fieldName = null; String relFieldName = null; if (keyMap.getFieldName().equals(keyMap.getRelFieldName())) { fieldName = keyMap.getFieldName(); relFieldName = "aa"; } else { fieldName = keyMap.getFieldName(); relFieldName = keyMap.getRelFieldName(); } keysMap.put("row", row++); keysMap.put("fieldName", fieldName); keysMap.put("relFieldName", relFieldName); keysList.add(keysMap); } relationMap.put("title", relation.getTitle()); relationMap.put("description", relation.getDescription()); relationMap.put("relEntity", relation.getRelEntityName()); relationMap.put("fkName", relation.getFkName()); relationMap.put("type", relation.getType()); relationMap.put("length", relation.getType().length()); relationMap.put("keysList", keysList); relationsList.add(relationMap); } // index list List<Map<String, Object>> indexList = new LinkedList<Map<String,Object>>(); for (int r = 0; r < entity.getIndexesSize(); r++) { List<String> fieldNameList = new LinkedList<String>(); ModelIndex index = entity.getIndex(r); for (Iterator<ModelIndex.Field> fieldIterator = index.getFields().iterator(); fieldIterator.hasNext();) { fieldNameList.add(fieldIterator.next().getFieldName()); } Map<String, Object> indexMap = new HashMap<String, Object>(); indexMap.put("name", index.getName()); indexMap.put("description", index.getDescription()); indexMap.put("fieldNameList", fieldNameList); indexList.add(indexMap); } entityMap.put("entityName", entityName); entityMap.put("helperName", helperName); entityMap.put("groupName", groupName); entityMap.put("plainTableName", entity.getPlainTableName()); entityMap.put("title", entity.getTitle()); entityMap.put("description", entityDescription); String entityLocation = entity.getLocation(); entityLocation = entityLocation.replaceFirst(System.getProperty("ofbiz.home") + "/", ""); entityMap.put("location", entityLocation); entityMap.put("javaNameList", javaNameList); entityMap.put("relationsList", relationsList); entityMap.put("indexList", indexList); entitiesList.add(entityMap); } } packageMap.put("packageName", pName); packageMap.put("entitiesList", entitiesList); packagesList.add(packageMap); } } catch (GenericEntityException e) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "EntityImportErrorRetrievingEntityNames", locale) + e.getMessage()); } resultMap.put("packagesList", packagesList); return resultMap; } public static Map<String, Object> exportEntityEoModelBundle(DispatchContext dctx, Map<String, ? extends Object> context) { String eomodeldFullPath = (String) context.get("eomodeldFullPath"); String entityPackageNameOrig = (String) context.get("entityPackageName"); String entityGroupId = (String) context.get("entityGroupId"); String datasourceName = (String) context.get("datasourceName"); String entityNamePrefix = (String) context.get("entityNamePrefix"); Locale locale = (Locale) context.get("locale"); if (datasourceName == null) datasourceName = "localderby"; ModelReader reader = dctx.getDelegator().getModelReader(); try { if (!eomodeldFullPath.endsWith(".eomodeld")) { eomodeldFullPath = eomodeldFullPath + ".eomodeld"; } File outdir = new File(eomodeldFullPath); if (!outdir.exists()) { outdir.mkdir(); } if (!outdir.isDirectory()) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsEomodelFullPathIsNotADirectory", UtilMisc.toMap("eomodeldFullPath", eomodeldFullPath), locale)); } if (!outdir.canWrite()) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsEomodelFullPathIsNotWriteable", UtilMisc.toMap("eomodeldFullPath", eomodeldFullPath), locale)); } Set<String> entityNames = new TreeSet<String>(); if (UtilValidate.isNotEmpty(entityPackageNameOrig)) { Set<String> entityPackageNameSet = new HashSet<String>(); entityPackageNameSet.addAll(StringUtil.split(entityPackageNameOrig, ",")); Debug.logInfo("Exporting with entityPackageNameSet: " + entityPackageNameSet, module); Map<String, TreeSet<String>> entitiesByPackage = reader.getEntitiesByPackage(entityPackageNameSet, null); for (Map.Entry<String, TreeSet<String>> entitiesByPackageMapEntry: entitiesByPackage.entrySet()) { entityNames.addAll(entitiesByPackageMapEntry.getValue()); } } else if (UtilValidate.isNotEmpty(entityGroupId)) { Debug.logInfo("Exporting entites from the Group: " + entityGroupId, module); entityNames.addAll(EntityGroupUtil.getEntityNamesByGroup(entityGroupId, dctx.getDelegator(), false)); } else { entityNames.addAll(reader.getEntityNames()); } Debug.logInfo("Exporting the following entities: " + entityNames, module); // remove all view-entity Iterator<String> filterEntityNameIter = entityNames.iterator(); while (filterEntityNameIter.hasNext()) { String entityName = filterEntityNameIter.next(); ModelEntity modelEntity = reader.getModelEntity(entityName); if (modelEntity instanceof ModelViewEntity) { filterEntityNameIter.remove(); } } // write the index.eomodeld file Map<String, Object> topLevelMap = new HashMap<String, Object>(); topLevelMap.put("EOModelVersion", "\"2.1\""); List<Map<String, Object>> entitiesMapList = new LinkedList<Map<String,Object>>(); topLevelMap.put("entities", entitiesMapList); for (String entityName: entityNames) { Map<String, Object> entitiesMap = new HashMap<String, Object>(); entitiesMapList.add(entitiesMap); entitiesMap.put("className", "EOGenericRecord"); entitiesMap.put("name", entityName); } UtilPlist.writePlistFile(topLevelMap, eomodeldFullPath, "index.eomodeld", true); // write each <EntityName>.plist file for (String curEntityName: entityNames) { ModelEntity modelEntity = reader.getModelEntity(curEntityName); UtilPlist.writePlistFile(modelEntity.createEoModelMap(entityNamePrefix, datasourceName, entityNames, reader), eomodeldFullPath, curEntityName +".plist", true); } Integer entityNamesSize = new Integer(entityNames.size()); return ServiceUtil.returnSuccess(UtilProperties.getMessage(resource, "WebtoolsEomodelExported", UtilMisc.toMap("entityNamesSize", entityNamesSize.toString(), "eomodeldFullPath", eomodeldFullPath), locale)); } catch (UnsupportedEncodingException e) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsEomodelSavingFileError", UtilMisc.toMap("errorString", e.toString()), locale)); } catch (FileNotFoundException e) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsEomodelFileOrDirectoryNotFound", UtilMisc.toMap("errorString", e.toString()), locale)); } catch (GenericEntityException e) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsEomodelErrorGettingEntityNames", UtilMisc.toMap("errorString", e.toString()), locale)); } } /** Performs an entity maintenance security check. Returns hasPermission=true * if the user has the ENTITY_MAINT permission. * @param dctx the dispatch context * @param context the context * @return return the result of the service execution */ public static Map<String, Object> entityMaintPermCheck(DispatchContext dctx, Map<String, ? extends Object> context) { GenericValue userLogin = (GenericValue) context.get("userLogin"); Locale locale = (Locale) context.get("locale"); Security security = dctx.getSecurity(); Map<String, Object> resultMap = null; if (security.hasPermission("ENTITY_MAINT", userLogin)) { resultMap = ServiceUtil.returnSuccess(); resultMap.put("hasPermission", true); } else { resultMap = ServiceUtil.returnFailure(UtilProperties.getMessage(resource, "WebtoolsPermissionError", locale)); resultMap.put("hasPermission", false); } return resultMap; } public static Map<String, Object> exportServiceEoModelBundle(DispatchContext dctx, Map<String, ? extends Object> context) { String eomodeldFullPath = (String) context.get("eomodeldFullPath"); String serviceName = (String) context.get("serviceName"); Locale locale = (Locale) context.get("locale"); if (eomodeldFullPath.endsWith("/")) { eomodeldFullPath = eomodeldFullPath + serviceName + ".eomodeld"; } if (!eomodeldFullPath.endsWith(".eomodeld")) { eomodeldFullPath = eomodeldFullPath + ".eomodeld"; } File outdir = new File(eomodeldFullPath); if (!outdir.exists()) { outdir.mkdir(); } if (!outdir.isDirectory()) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsEomodelFullPathIsNotADirectory", UtilMisc.toMap("eomodeldFullPath", eomodeldFullPath), locale)); } if (!outdir.canWrite()) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsEomodelFullPathIsNotWriteable", UtilMisc.toMap("eomodeldFullPath", eomodeldFullPath), locale)); } try { ArtifactInfoFactory aif = ArtifactInfoFactory.getArtifactInfoFactory("default"); ServiceArtifactInfo serviceInfo = aif.getServiceArtifactInfo(serviceName); serviceInfo.writeServiceCallGraphEoModel(eomodeldFullPath); } catch (GeneralException e) { Debug.logError(e, module); return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsEomodelErrorGettingEntityNames", UtilMisc.toMap("errorString", e.toString()), locale)); } catch (UnsupportedEncodingException e) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsEomodelSavingFileError", UtilMisc.toMap("errorString", e.toString()), locale)); } catch (FileNotFoundException e) { return ServiceUtil.returnError(UtilProperties.getMessage(resource, "WebtoolsEomodelFileOrDirectoryNotFound", UtilMisc.toMap("errorString", e.toString()), locale)); } return ServiceUtil.returnSuccess(); } }