1 | # |
---|
2 | import transaction |
---|
3 | import os, sys, re, string |
---|
4 | from sets import Set |
---|
5 | from StringIO import StringIO |
---|
6 | from time import gmtime, strftime |
---|
7 | from zLOG import LOG, INFO |
---|
8 | from zExceptions import BadRequest |
---|
9 | from App.config import getConfiguration |
---|
10 | from Products.CMFCore.utils import getToolByName |
---|
11 | from Products.CMFCore.DirectoryView import addDirectoryViews |
---|
12 | from Globals import package_home |
---|
13 | |
---|
14 | from fixes import fix |
---|
15 | from ${namespace_package}.${namespace_package2}.${package} import GLOBALS |
---|
16 | |
---|
17 | IMPORT_POLICY = "backup" |
---|
18 | |
---|
19 | ###################################################################### |
---|
20 | ## IMPORTING UTILS ## |
---|
21 | ###################################################################### |
---|
22 | osp = os.path |
---|
23 | ALLOWED_IMPORT_POLICY = ["only_new", "backup", "overwrite"] |
---|
24 | INTRO_TO_INSTANCE = "< Started copying object files from Product import directory to Instance one." |
---|
25 | SUMMARY_TO_INSTANCE = "> Finished copying." |
---|
26 | INTRO_TO_ROOT = "< Started import %s file[s] with '%s' policy." |
---|
27 | SUMMARY_TO_ROOT = "> Finished importing." |
---|
28 | INTRO_CLEAN = "< Started cleaning Instance import directory." |
---|
29 | SUMMARY_CLEAN = "> Finished cleaning." |
---|
30 | CREXP_INVALID_ID = re.compile('^The id \"(.*?)\" is invalid - it is already in use.$', re.DOTALL|re.IGNORECASE|re.MULTILINE) |
---|
31 | CSS_BASE_IDS_QPSD053 = ['id','expression','enabled','cookable','media','rel','title','rendering'] # supporting qPSD-0.5.3 version |
---|
32 | ################ CHECK IMPORTING ################ |
---|
33 | def checkIfImport(): |
---|
34 | """ Return if perform importing, based on checking |
---|
35 | *zexp files in <SkinProduct>/import directory. |
---|
36 | """ |
---|
37 | instance_ipath, product_ipath = getImportedPathes() |
---|
38 | product_ilist = [i for i in os.listdir(product_ipath) \ |
---|
39 | if osp.isfile(osp.join(product_ipath,i)) and i.endswith('.zexp')] |
---|
40 | if product_ilist: |
---|
41 | return 1 |
---|
42 | return 0 |
---|
43 | |
---|
44 | ################ IMPORTING TO PLONE'S IMPORT DIR ################ |
---|
45 | def getImportedPathes(): |
---|
46 | """ Return Plone instance and Skin product import pathes.""" |
---|
47 | # Based on instance path, construct import pathes |
---|
48 | cfg = getConfiguration() |
---|
49 | instance_ipath = osp.join(cfg.instancehome, "import") |
---|
50 | product_ipath = osp.join(package_home(GLOBALS), "import") |
---|
51 | # Check presence of Product import directory |
---|
52 | if not osp.isdir(product_ipath): |
---|
53 | raise BadRequest, "Skin Product's import directory '%s' - does not exist or is'nt direcory" % product_ipath |
---|
54 | # Check presence of Instance import directory |
---|
55 | if not osp.isdir(instance_ipath): |
---|
56 | raise BadRequest, "Instance import directory '%s' - does not exist or isn't direcory" % instance_ipath |
---|
57 | return [instance_ipath, product_ipath] |
---|
58 | |
---|
59 | def copyFile(src_dir, dst_dir, f_name): |
---|
60 | """ Copy file from src_dir to dst_dir under original name.""" |
---|
61 | try: |
---|
62 | src_file = open(osp.join(src_dir, f_name),"rb") |
---|
63 | dst_file = open(osp.join(dst_dir, f_name),"wb") |
---|
64 | dst_file.write(src_file.read()) |
---|
65 | dst_file.close() |
---|
66 | src_file.close() |
---|
67 | except Exception, e: |
---|
68 | msg = "!!! In copying files from < %s > dir to < %s > dir exception occur. Details: %s." % (src_dir,dst_dir, str(e)) |
---|
69 | print >> import_out, msg |
---|
70 | LOG('performImportToPortal',INFO,'copyFile', msg) |
---|
71 | |
---|
72 | def moveToTemp(same_instance_files, instance_ipath, temp_dir_path): |
---|
73 | """ Move samenamed files from Instanse's dir to temp dir.""" |
---|
74 | os.mkdir(temp_dir_path) # Create temp back_[date] dir |
---|
75 | try: |
---|
76 | [copyFile(instance_ipath, temp_dir_path, f_name) for f_name in same_instance_files] |
---|
77 | [os.remove(osp.join(instance_ipath, f_name)) for f_name in same_instance_files] |
---|
78 | except Exception, e: |
---|
79 | msg = "!!! Exception occur during moving files from Instance's dir to temp dir. Detaile:%s." % str(e) |
---|
80 | print >> import_out, msg |
---|
81 | LOG('performImportToPortal',INFO,'moveToTemp', msg) |
---|
82 | |
---|
83 | def copyToInstanceImport(): |
---|
84 | """ Perform copying imported files from <SkinProduct>/import dir |
---|
85 | to Plone's instance import dir. |
---|
86 | """ |
---|
87 | print >> import_out, INTRO_TO_INSTANCE |
---|
88 | instance_ipath, product_ipath = getImportedPathes() |
---|
89 | # Compose temp dir back_[date] dir path in Instance import directory |
---|
90 | temp_dir_id = "back_%s" % strftime("%Y%m%d%H%M%S", gmtime()) |
---|
91 | temp_dir_path = osp.join(instance_ipath, temp_dir_id) |
---|
92 | # Get *.zexp files from Skin Product's import dir and Plone's instance import dir files |
---|
93 | product_ilist = [i for i in os.listdir(product_ipath) \ |
---|
94 | if osp.isfile(osp.join(product_ipath,i)) and i.endswith('.zexp')] |
---|
95 | instance_ilist = [i for i in os.listdir(instance_ipath) \ |
---|
96 | if osp.isfile(osp.join(instance_ipath,i)) and i.endswith('.zexp')] |
---|
97 | # Check for presence samenamed files in Instance and Product import directories. |
---|
98 | same_instance_files = [f_name for f_name in instance_ilist if f_name in product_ilist] |
---|
99 | if same_instance_files: |
---|
100 | moveToTemp(same_instance_files, instance_ipath, temp_dir_path) |
---|
101 | # Copy all *zexp files from Product's import dir to Instance's import dir |
---|
102 | [copyFile(product_ipath, instance_ipath, f_name) for f_name in product_ilist] |
---|
103 | print >> import_out, SUMMARY_TO_INSTANCE |
---|
104 | return [instance_ipath, product_ipath, temp_dir_path, product_ilist] |
---|
105 | |
---|
106 | ################ IMPORTING TO PORTAL ################ |
---|
107 | def importObject(portal, file_name): |
---|
108 | """ Work around old Zope bug in importing.""" |
---|
109 | try: |
---|
110 | portal.manage_importObject(file_name) |
---|
111 | except: |
---|
112 | portal._p_jar = portal.Destination()._p_jar |
---|
113 | portal.manage_importObject(file_name) |
---|
114 | |
---|
115 | def makeBackUp(portal, portal_objects, temp_dir_path, obj_id): |
---|
116 | """ Perfom backup same named portal objects in temp folder.""" |
---|
117 | # Get id of temp folder-object |
---|
118 | durty_path,temp_id = osp.split(temp_dir_path) |
---|
119 | if not temp_id: |
---|
120 | durty_path,temp_id = osp.split(durty_path) |
---|
121 | # Get temp folder-object |
---|
122 | if temp_id not in portal_objects: |
---|
123 | portal.invokeFactory('Large Plone Folder', id=temp_id) |
---|
124 | print >> import_out, "! Created '%s' backup directory with same-ids " \ |
---|
125 | "objects from portal root." % temp_id |
---|
126 | temp_dir = getattr(portal, temp_id) |
---|
127 | # Move object with same id to temp folder-object |
---|
128 | #get_transaction().commit(1) |
---|
129 | transaction.savepoint() |
---|
130 | obj = portal.manage_cutObjects(ids=[obj_id]) |
---|
131 | temp_dir.manage_pasteObjects(obj) |
---|
132 | print >> import_out, "! '%s' Object moved from portal root to '%s' backup directory." % (obj_id, temp_id) |
---|
133 | |
---|
134 | def performImport(portal, temp_dir_path, file_name): |
---|
135 | """ Importing an object to portal.""" |
---|
136 | portal_objects = portal.objectIds() |
---|
137 | try: |
---|
138 | portal.manage_importObject(file_name) |
---|
139 | except Exception, e: |
---|
140 | msg = str(e) |
---|
141 | is_invalid_id = CREXP_INVALID_ID.match(msg) |
---|
142 | if is_invalid_id: |
---|
143 | obj_id = is_invalid_id.group(1) |
---|
144 | if IMPORT_POLICY == "only_new": |
---|
145 | msg = "! Object with '%s' id was not importing because it's already exist " \ |
---|
146 | "in portal root." % obj_id |
---|
147 | print >> import_out, msg |
---|
148 | elif IMPORT_POLICY == "backup": |
---|
149 | makeBackUp(portal, portal_objects, temp_dir_path, obj_id) |
---|
150 | importObject(portal, file_name) |
---|
151 | elif IMPORT_POLICY == "overwrite": |
---|
152 | portal.manage_delObjects(ids=[obj_id]) |
---|
153 | importObject(portal, file_name) |
---|
154 | else: |
---|
155 | # work around old Zope bug in importing |
---|
156 | portal._p_jar = portal.Destination()._p_jar |
---|
157 | portal.manage_importObject(file_name) |
---|
158 | |
---|
159 | def importToPortalRoot(portal, product_file_names, temp_dir_path): |
---|
160 | """ Import all objects from *zexp files to portal root (based on IMPORT_POLICY).""" |
---|
161 | if not IMPORT_POLICY in ALLOWED_IMPORT_POLICY: |
---|
162 | raise Exception("%s - wrong import policy, must be one of the %s" \ |
---|
163 | % (IMPORT_POLICY, ALLOWED_IMPORT_POLICY) ) |
---|
164 | print >> import_out, INTRO_TO_ROOT % (product_file_names, IMPORT_POLICY) |
---|
165 | for file_name in product_file_names: |
---|
166 | try: |
---|
167 | # Temporary allow implicitly adding Large Plone Folder |
---|
168 | types_tool = getToolByName(portal, 'portal_types') |
---|
169 | lpf_fti = types_tool['Large Plone Folder'] |
---|
170 | lpf_global_setting = lpf_fti.global_allow |
---|
171 | lpf_fti.global_allow = 1 |
---|
172 | try: |
---|
173 | performImport(portal, temp_dir_path, file_name) |
---|
174 | finally: |
---|
175 | lpf_fti.global_allow = lpf_global_setting |
---|
176 | except Exception, error: |
---|
177 | msg = '!!! Under "%s" policy importing exception occur: %s.' % (IMPORT_POLICY, str(error)) |
---|
178 | print >> import_out, msg |
---|
179 | LOG('performImportToPortal',INFO,'importToPortalRoot', msg) |
---|
180 | print >> import_out, SUMMARY_TO_ROOT |
---|
181 | |
---|
182 | ################ CLEANING PLONE'S IMPORT DIR ################ |
---|
183 | def cleanInstanceImport(instance_ipath, product_file_names, temp_dir_path): |
---|
184 | """ Cleaning Plone's import dir.""" |
---|
185 | print >> import_out, INTRO_CLEAN |
---|
186 | # Erase all copied *zexp files from Instance's import dir |
---|
187 | for f_name in product_file_names: |
---|
188 | f_path = osp.join(instance_ipath, f_name) |
---|
189 | if osp.exists(f_path) and osp.isfile(f_path): |
---|
190 | os.remove(f_path) |
---|
191 | else: |
---|
192 | msg = '! "%s" file was not deleted from "%s" import directory.' %\ |
---|
193 | (f_name, osp.join(instance_ipath)) |
---|
194 | print >> import_out, msg |
---|
195 | LOG('performImportToPortal',INFO,'cleanInstanceImport', msg) |
---|
196 | # Move all files from temp back_[date] dir to Instance's import dir |
---|
197 | if osp.exists(temp_dir_path) and osp.isdir(temp_dir_path): |
---|
198 | f_names = os.listdir(temp_dir_path) |
---|
199 | try: |
---|
200 | [copyFile(temp_dir_path, instance_ipath, f_name) for f_name in f_names] |
---|
201 | [os.remove(osp.join(temp_dir_path, f_name)) for f_name in f_names] |
---|
202 | # Erase temp back_[date] dir |
---|
203 | os.rmdir(temp_dir_path) |
---|
204 | except Exception, e: |
---|
205 | msg = "!!! In moving files from temp dir to Instance's import dir exception occur." |
---|
206 | print >> import_out, msg |
---|
207 | LOG('performImportToPortal',INFO,'moveFromTempToImport', msg) |
---|
208 | print >> import_out, SUMMARY_CLEAN |
---|
209 | |
---|
210 | def fixImportingIssues(portal, beforeimporting_objects): |
---|
211 | ''' Fix defects of importing process: reindexing, other''' |
---|
212 | afterimporting_objects = portal.objectItems() |
---|
213 | diff_objects = list(Set(afterimporting_objects)-Set(beforeimporting_objects)) |
---|
214 | for id, ob in diff_objects: |
---|
215 | if id.startswith('back_'): |
---|
216 | continue |
---|
217 | fix(ob) |
---|
218 | |
---|
219 | ################ MAIN ################ |
---|
220 | def performImportToPortal(portal): |
---|
221 | """ Import objects from Skin Product to Portal root.""" |
---|
222 | globals()['import_out'] = StringIO() |
---|
223 | instance_ipath, product_ipath, temp_dir_path, product_file_names = copyToInstanceImport() |
---|
224 | if product_file_names: |
---|
225 | beforeimporting_objects = portal.objectItems() |
---|
226 | importToPortalRoot(portal, product_file_names, temp_dir_path) |
---|
227 | fixImportingIssues(portal, beforeimporting_objects) |
---|
228 | cleanInstanceImport(instance_ipath, product_file_names, temp_dir_path) |
---|
229 | else: |
---|
230 | print >> import_out, "!!! Failure importing: there is no file for importing to be found." |
---|
231 | result = import_out.getvalue() |
---|
232 | del globals()['import_out'] |
---|
233 | return result |
---|
234 | |
---|
235 | # |
---|