From 4b23ec7c0a12a63912c1d50c02c162ea4c417dda Mon Sep 17 00:00:00 2001 From: Matt Nash Date: Thu, 11 Apr 2013 10:36:48 -0500 Subject: [PATCH] Issue #1870 implement PathManager interface in Python to allow Python code to get files Change-Id: I0192c996533b1539194aaeba0213074bef8a4717 Former-commit-id: e3df8efa51ad95c952318b59edca702157a59856 --- .../.classpath | 7 + .../.project | 34 ++++ .../.pydevproject | 7 + .../.settings/org.eclipse.jdt.core.prefs | 7 + .../META-INF/MANIFEST.MF | 13 ++ .../build.properties | 4 + .../common_static/base/python/IPathManager.py | 61 ++++++ .../base/python/LocalizationFile.py | 122 ++++++++++++ .../base/python/LocalizationUtil.py | 86 +++++++++ .../common_static/base/python/LockingFile.py | 58 ++++++ .../common_static/base/python/PathManager.py | 173 ++++++++++++++++++ 11 files changed, 572 insertions(+) create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/.classpath create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/.project create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/.pydevproject create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/.settings/org.eclipse.jdt.core.prefs create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/META-INF/MANIFEST.MF create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/build.properties create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/IPathManager.py create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LocalizationFile.py create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LocalizationUtil.py create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LockingFile.py create mode 100644 edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/PathManager.py diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/.classpath b/edexOsgi/com.raytheon.uf.common.localization.python/.classpath new file mode 100644 index 0000000000..ad32c83a78 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/.project b/edexOsgi/com.raytheon.uf.common.localization.python/.project new file mode 100644 index 0000000000..f13e215048 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/.project @@ -0,0 +1,34 @@ + + + com.raytheon.uf.common.localization.python + + + + + + org.python.pydev.PyDevBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.python.pydev.pythonNature + + diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/.pydevproject b/edexOsgi/com.raytheon.uf.common.localization.python/.pydevproject new file mode 100644 index 0000000000..f4a659751e --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/.pydevproject @@ -0,0 +1,7 @@ + + + + +python 2.7 +Default + diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/.settings/org.eclipse.jdt.core.prefs b/edexOsgi/com.raytheon.uf.common.localization.python/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..c537b63063 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.localization.python/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..b6bbbaffe7 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Python +Bundle-SymbolicName: com.raytheon.uf.common.localization.python +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: RAYTHEON +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Require-Bundle: com.raytheon.uf.common.localization;bundle-version="1.12.1174", + com.raytheon.uf.common.python;bundle-version="1.12.1174", + com.raytheon.uf.common.python.concurrent;bundle-version="1.0.0", + com.raytheon.uf.common.status;bundle-version="1.12.1174", + org.jep;bundle-version="1.0.0" +Export-Package: com.raytheon.uf.common.localization.python diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/build.properties b/edexOsgi/com.raytheon.uf.common.localization.python/build.properties new file mode 100644 index 0000000000..34d2e4d2da --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/IPathManager.py b/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/IPathManager.py new file mode 100644 index 0000000000..9dcd2d875b --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/IPathManager.py @@ -0,0 +1,61 @@ +# # +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +# # + +# +# Class with abstract methods for use with localization files. +# One implementation of this will be a pure python implementation +# for use outside of the AWIPS II architecture, and one will follow +# the AWIPS II architecture. +# +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 03/12/13 mnash Initial Creation. +# +# +# + +import abc + +class IPathManager(object): + + __metaclass__ = abc.ABCMeta + + def __init__(self): + return + + @abc.abstractmethod + def getLocalizationFile(self, name, context=None): + pass + + @abc.abstractmethod + def getTieredLocalizationFile(self, loctype, name): + pass + + @abc.abstractmethod + def listFiles(self, name, extensions, recursive, filesOnly, loctype=None, loclevel=None, locname=None): + pass + + @abc.abstractmethod + def getAvailableLevels(self): + pass \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LocalizationFile.py b/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LocalizationFile.py new file mode 100644 index 0000000000..8118857ca9 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LocalizationFile.py @@ -0,0 +1,122 @@ +# # +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +# # + +# +# Python can have these and be able to make modifications and save +# files back to the server through this class. +# +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 03/12/13 mnash Initial Creation. +# +# +# + +import JUtil +from datetime import datetime +from LockingFile import File + +from java.io import File as JavaFile +from com.raytheon.uf.common.localization import LocalizationContext_LocalizationLevel as JavaLocalizationLevel + + +class LocalizationFile(JUtil.JavaWrapperClass): + + def __init__(self, wrappedObject): + self.jobj = wrappedObject + + def save(self): + ''' + @summary: Used to save the localization file back to localization + ''' + return self.jobj.save() + + def delete(self): + ''' + @summary: Used to delete the localization file from localization + ''' + return self.jobj.delete() + + def exists(self): + ''' + @summary: Check if the file actually exists + ''' + return self.jobj.exists() + + def getName(self): + ''' + @summary: Get the name of the file. + ''' + return self.jobj.getName() + + def getPath(self): + ''' + @summary: Get the path of the file + ''' + return self.jobj.getFile().getAbsolutePath() + + def getFile(self, mode='r'): + ''' + @param mode: The mode. + @summary: Return a file handle to the file + ''' + retrieveFile = True + if mode == 'w': + retrieveFile = False + return File(self.jobj.getFile(retrieveFile), self.getName(), mode) + + def getTimeStamp(self): + ''' + @summary: Get the timestamp of the file as a python datetime. + ''' + return datetime.fromtimestamp(self.jobj.getTimeStamp().getTime() / 1000.0) + + def isAvailableOnServer(self): + ''' + @summary: Is this file available on the server + ''' + return self.jobj.isAvailableOnServer() + + def isDirectory(self): + ''' + @summary: Is this a directory. + ''' + return self.jobj.isDirectory() + + def isProtected(self): + ''' + @summary: Is this file protected. + ''' + return self.jobj.isProtected() + + def __eq__(self, other): + return self.jobj.equals(other.jobj) + + def toJavaObj(self): + ''' + @summary: Returns the behind the scenes Java object + ''' + return self.jobj + + diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LocalizationUtil.py b/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LocalizationUtil.py new file mode 100644 index 0000000000..2374c3b2a4 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LocalizationUtil.py @@ -0,0 +1,86 @@ +# # +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +# # + +# +# Methods to aid in using the path manager from Python as well as other features. +# Contains internal classes to help with the transition from strings in Python +# to Java Localizationlevel and LocalizationType +# +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 03/12/13 mnash Initial Creation. +# +# +# + +import os +import imp + +from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as JavaLocalizationType, LocalizationContext_LocalizationLevel as JavaLocalizationLevel + +class LocalizationLevel(object): + ''' + @summary: Can use cmp() to compare the levels, and can use values() to get all possible levels + ''' + @staticmethod + def cmp(level1, level2): + return JavaLocalizationLevel.compare(level1,level2) + + @staticmethod + def values(): + jvals = JavaLocalizationLevel.values() + vals = list() + for val in jvals : + vals.append(val.name()) + return vals + + @staticmethod + def valueOf(value): + return JavaLocalizationLevel.valueOf(value) + +class LocalizationType(object): + + @staticmethod + def values(): + jvals = JavaLocalizationType.values() + vals = list() + for val in jvals : + vals.append(val.name()) + return vals + + @staticmethod + def valueOf(value): + return JavaLocalizationType.valueOf(value) + +def loadModule(filename): + ''' + @param filename: the fully qualified name of the file + @return: the module that was loaded + @summary: This function takes a filename and find the module, + loads it and returns that module + ''' + path = os.path.splitext(filename)[0] + filename = os.path.split(path)[1] + fp, pathname, description = imp.find_module(filename) + return imp.load_module(filename, fp, pathname, description) \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LockingFile.py b/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LockingFile.py new file mode 100644 index 0000000000..fa74c47c2b --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/LockingFile.py @@ -0,0 +1,58 @@ +# # +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +# # + +# +# Python needs to have access to a context, not to create though +# +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 03/12/13 mnash Initial Creation. +# +# +# + +from com.raytheon.uf.common.localization import FileLocker, FileLocker_Type as Type +from java.io import File as JavaFile +from java.lang import Object + + +class File(file): + + def __init__(self, file, name, mode): + self.lockerObject = Object() + + type = Type.WRITE + if mode == 'r': + type = Type.READ + + self.file = file + locked = FileLocker.lock(self.lockerObject, file, type) + # log if not locked, because that's bad + super(File, self).__init__(file.getAbsolutePath(), mode) + + def close(self): + FileLocker.unlock(self.lockerObject, self.file) + return super(File,self).close() + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/PathManager.py b/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/PathManager.py new file mode 100644 index 0000000000..4b9fef5388 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.localization.python/utility/common_static/base/python/PathManager.py @@ -0,0 +1,173 @@ +# # +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +# # + +# +# Python should use this interface to get to the localization files. +# +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 03/18/13 mnash Initial Creation. +# +# +# + +import os, os.path +import IPathManager +import JUtil +from jep import jarray + +from LocalizationFile import LocalizationFile +from LockingFile import File + +from com.raytheon.uf.common.localization import PathManagerFactory +from com.raytheon.uf.common.localization import LocalizationContext as JavaLocalizationContext +from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType, LocalizationContext_LocalizationLevel as LocalizationLevel +from java.io import File as JavaFile +from java.lang import String + +class PathManager(IPathManager.IPathManager): + + def __init__(self): + self.jpathManager = PathManagerFactory.getPathManager() + + def getLocalizationFile(self, name, loctype=None, loclevel=None, locname=None): + ''' + @param context: the localization context for which to get the file + @param name: the name and path of the file + @param loctype: the LocalizationType (COMMON_STATIC,CAVE_STATIC...) + @param loclevel: the localization level (BASE,SITE,USER...) + @param locname: the localization name if desired + @return: the localization file + @summary: This method returns the localization file based on the context and the name + ''' + context = self._getContext(loctype, loclevel, locname) + if context is not None and len(context) == 1: + lFile = self.jpathManager.getLocalizationFile(context[0], name) + else : + lFile = self.jpathManager.getStaticLocalizationFile(name) + if lFile is not None: + return LocalizationFile(lFile) + + def getTieredLocalizationFile(self, loctype, name): + ''' + @param loctype: The localization type to look in + @param name: The name of the file + @return: a dictionary of string to localization file + @summary: Returns the localization levels available for the file given + ''' + jtype = self._convertType(loctype) + jMap = JUtil.javaMapToPyDict(self.jpathManager.getTieredLocalizationFile(jtype, name)) + vals = dict() + for level in jMap: + jlevel = self._convertLevel(level) + vals[jlevel.name()] = LocalizationFile(jMap.get(level)) + return vals + + def listFiles(self, name, extensions, recursive, filesOnly, loctype=None, loclevel=None, locname=None): + ''' + @param name: the name and path of the file + @param extensions: a list of the file extensions to filter on + @param recursive: whether or not to search through the directory recursively + @param filesOnly: whether or not directories should be included in the list + @param loctype: the localization type for which to get the file + @param loclevel: the localization level for which to get the file + @param locname: the name for which to get + @return: a list of the file paths + @summary: This method returns the list of fully qualified file paths for a + directory or a directory and its sub-directories + ''' + contexts = self._getContext(loctype, loclevel, locname) + extensionSize = len(extensions) + extArr = jarray(extensionSize, String) + for i in range(extensionSize): + extArr[i] = String(extensions[i]) + + if contexts is not None : + jfiles = self.jpathManager.listFiles(contexts, name, extArr, recursive, filesOnly) + else : + jfiles = self.jpathManager.listStaticFiles(name, extArr, recursive, filesOnly) + if jfiles is not None : + files = list() + for file in jfiles : + files.append(LocalizationFile(file)) + return files + + def getAvailableLevels(self): + ''' + @return: the levels available to the caller + @summary: This method returns the list of available levels. + ''' + jLevels = self.jpathManager.getAvailableLevels() + levels = list() + for level in jLevels : + levels.append(level.name()) + return levels + + # converts a type of a list of types to the java counterparts + def _convertType(self, loctype): + if loctype is not None: + jtype = loctype + if isinstance(loctype, basestring): + jtype = LocalizationType.valueOf(loctype) + elif isinstance(loctype, list): + jtype = [] + for i in range(loctype): + jtype[i] = self._convertType(loctype[i]) + return jtype + + # converts a level or a list of levels to the java counterparts + def _convertLevel(self, loclevel): + if loclevel is not None : + jlevel = loclevel + if isinstance(loclevel, basestring): + jlevel = LocalizationLevel.valueOf(loclevel) + elif isinstance(loclevel, list): + jlevel = [] + for i in range(loclevel): + jlevel[i] = self._convertLevel(loclevel[i]) + return jlevel + + def _getContext(self, loctype, loclevel, locname=None): + jtype = self._convertType(loctype) + jlevel = self._convertLevel(loclevel) + context = None + if isinstance(jtype, list) is False: + if jtype is not None : + jtype = [jtype] + if jlevel is not None : + jlevel = [jlevel] + return self._contextForList(jtype, jlevel, locname) + + def _contextForList(self, loctypes, loclevels, locname=None): + # gets the contexts in list form, for ease of use, we always use a list of contexts + # for methods that can take both + contexts = jarray(len(loctypes), JavaLocalizationContext) + for i in range(len(loctypes)): + if locname is None and loclevels is None: + return None + elif loclevels is not None : + contexts[i] = self.jpathManager.getContext(loctypes[i], loclevels[i]) + if locname is not None : + contexts[i].setContextName(locname) + return contexts