|
1 # |
|
2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # |
|
16 ''' |
|
17 A plugin implementation for content selection from ConfigurationLayers. |
|
18 ''' |
|
19 |
|
20 |
|
21 import re |
|
22 import os |
|
23 import sys |
|
24 import logging |
|
25 import shutil |
|
26 |
|
27 import __init__ |
|
28 |
|
29 from cone.public import exceptions,plugin,utils,api,container |
|
30 from contentplugin import contentmlparser |
|
31 |
|
32 class ContentImpl(plugin.ImplBase): |
|
33 """ |
|
34 ContentImpl plugin finds all content resources from each layer and copies |
|
35 them to the output correctly. It follows the Configuration project override |
|
36 rules, so that the topmost layer files override files on the previous layers. |
|
37 """ |
|
38 |
|
39 IMPL_TYPE_ID = 'content' |
|
40 |
|
41 def __init__(self,ref,configuration): |
|
42 """ |
|
43 Overloading the default constructor |
|
44 """ |
|
45 plugin.ImplBase.__init__(self,ref,configuration) |
|
46 self.desc = "" |
|
47 self.logger = logging.getLogger('cone.content(%s)' % self.ref) |
|
48 self.errors = False |
|
49 |
|
50 def list_output_files(self): |
|
51 """ |
|
52 Return a list of output files as an array. |
|
53 """ |
|
54 if not self.errors: |
|
55 copylist = self.get_full_copy_list() |
|
56 outputfiles = [entry[1] for entry in copylist] |
|
57 return outputfiles |
|
58 else: |
|
59 return [] |
|
60 |
|
61 def get_refs(self): |
|
62 refs = [] |
|
63 for output in self.outputs: |
|
64 refs.extend(output.get_refs()) |
|
65 if refs: |
|
66 return refs |
|
67 else: |
|
68 return None |
|
69 |
|
70 def get_full_copy_list(self, print_info=False): |
|
71 fullcopylist = [] |
|
72 for output in self.outputs: |
|
73 for input in output.inputs: |
|
74 copylist = [] |
|
75 if print_info: |
|
76 self.logger.info('Content copy items from %s to %s' % (input.dir,os.path.join(self.output,output.dir))) |
|
77 |
|
78 if input.__class__.__name__ == "ContentInput": |
|
79 copylist = self.create_copy_list(content=self.configuration.layered_content(), |
|
80 input=input.dir, |
|
81 output=os.path.join(self.output,output.dir), |
|
82 include_pattern=input.get_include_pattern(), |
|
83 exclude_pattern=input.get_exclude_pattern(), |
|
84 files=input.get_filelist(), |
|
85 flatten=output.flatten, |
|
86 output_file=output.file) |
|
87 elif input.__class__.__name__ == "ExternalContentInput": |
|
88 #Handling external inputs separately |
|
89 if input.dir != None: |
|
90 fulldir = os.path.abspath(os.path.join(self.configuration.get_project().get_storage().get_path(),input.dir)) |
|
91 else: |
|
92 fulldir = self.configuration.get_project().get_storage().get_path() |
|
93 |
|
94 data = container.DataContainer() |
|
95 for root, dirs, files in os.walk(fulldir): |
|
96 for f in files: |
|
97 filepath = utils.resourceref.norm(os.path.join(root, f)) |
|
98 key = utils.resourceref.replace_dir(filepath,fulldir,"") |
|
99 data.add_value(key,filepath) |
|
100 #data.add_value(filepath,filepath) |
|
101 copylist = self.create_copy_list(content=data, |
|
102 input=input.dir, |
|
103 output=os.path.join(self.output,output.dir), |
|
104 include_pattern=input.get_include_pattern(), |
|
105 exclude_pattern=input.get_exclude_pattern(), |
|
106 files=input.get_filelist(), |
|
107 flatten=output.flatten, |
|
108 output_file=output.file, |
|
109 external=True) |
|
110 else: |
|
111 logging.getLogger('cone.content').warning("Unknown input %s" % (input.__class__.__name__)) |
|
112 |
|
113 fullcopylist += copylist |
|
114 |
|
115 return fullcopylist |
|
116 |
|
117 def generate(self, context=None): |
|
118 """ |
|
119 Generate the given implementation. |
|
120 """ |
|
121 self.logger.info('Generating') |
|
122 self.create_output() |
|
123 return |
|
124 |
|
125 def create_output(self,layers=None): |
|
126 """ |
|
127 Create the output directory from the content folder files |
|
128 """ |
|
129 if not self.errors: |
|
130 datacontainer = self.configuration.layered_content(layers) |
|
131 #root = self.configuration.get_root() |
|
132 copylist = self.get_full_copy_list(True) |
|
133 for copy_item in copylist: |
|
134 sourceref = copy_item[0] |
|
135 targetfile = copy_item[1] |
|
136 external = copy_item[2] |
|
137 |
|
138 self.logger.info('Copy from %s to %s' % (sourceref,targetfile)) |
|
139 if not os.path.exists(os.path.dirname(targetfile)): |
|
140 os.makedirs(os.path.dirname(targetfile)) |
|
141 if not external: |
|
142 outfile = open(targetfile,"wb") |
|
143 res = self.configuration.get_storage().open_resource(sourceref,"rb") |
|
144 outfile.write(res.read()) |
|
145 else: |
|
146 shutil.copyfile(sourceref,targetfile) |
|
147 return |
|
148 else: |
|
149 self.logger.error('Plugin had errors! Bailing out!') |
|
150 |
|
151 |
|
152 def create_copy_list(self, **kwargs): |
|
153 """ |
|
154 Return a list copy list where each element is a (from,to) tuple |
|
155 """ |
|
156 datacontainer = kwargs.get('content',None) |
|
157 input_dir = kwargs.get('input','') |
|
158 output_dir = kwargs.get('output','') |
|
159 output_file = kwargs.get('output_file','') |
|
160 include_filter= kwargs.get('include_pattern','') |
|
161 exclude_filter= kwargs.get('exclude_pattern','') |
|
162 files = kwargs.get('files',[]) |
|
163 flatten = kwargs.get('flatten',False) |
|
164 external = kwargs.get('external',False) |
|
165 copylist = [] |
|
166 contentfiles = datacontainer.list_keys() |
|
167 """ |
|
168 First get only the files list from content files. |
|
169 Then apply the possible filters. |
|
170 """ |
|
171 if input_dir == None: |
|
172 self.logger.warning("Input dir is none!") |
|
173 |
|
174 |
|
175 if files != []: |
|
176 for f in files: |
|
177 if f in contentfiles: |
|
178 pass |
|
179 elif f not in contentfiles: |
|
180 self.logger.info("File: %s not found in content" % f) |
|
181 |
|
182 |
|
183 if files != []: |
|
184 filesfunc = lambda x: x.lower() in [f.lower() for f in files] |
|
185 contentfiles = filter(filesfunc, contentfiles) |
|
186 if include_filter != "": |
|
187 filter_regexp = include_filter |
|
188 filter_regexp = filter_regexp.replace('.','\.') |
|
189 filter_regexp = filter_regexp.replace('*','.*') |
|
190 self.logger.info("filtering with include %s" % filter_regexp) |
|
191 contentfiles = utils.resourceref.filter_resources(contentfiles,filter_regexp) |
|
192 if exclude_filter != "": |
|
193 filter_regexp = exclude_filter |
|
194 filter_regexp = filter_regexp.replace('.','\.') |
|
195 filter_regexp = filter_regexp.replace('*','.*') |
|
196 self.logger.info("filtering with exclude %s" % filter_regexp) |
|
197 contentfiles = utils.resourceref.neg_filter_resources(contentfiles,filter_regexp) |
|
198 for outfile in contentfiles: |
|
199 sourcefile = "" |
|
200 targetfile = "" |
|
201 |
|
202 if input_dir != None and outfile.startswith(input_dir): |
|
203 sourcefile = datacontainer.get_value(outfile) |
|
204 if flatten: |
|
205 targetfile = utils.resourceref.join_refs([output_dir, os.path.basename(outfile)]) |
|
206 targetfile = utils.resourceref.norm(targetfile) |
|
207 else: |
|
208 targetfile = utils.resourceref.replace_dir(outfile,input_dir,output_dir) |
|
209 elif external: |
|
210 #External inputs |
|
211 sourcefile = utils.resourceref.norm(datacontainer.get_value(outfile)) |
|
212 |
|
213 if flatten: |
|
214 targetfile = utils.resourceref.join_refs([output_dir, os.path.basename(sourcefile)]) |
|
215 targetfile = utils.resourceref.norm(targetfile) |
|
216 else: |
|
217 fulldir = os.path.abspath(os.path.join(self.configuration.get_project().get_storage().get_path(),input_dir)) |
|
218 targetfile = utils.resourceref.replace_dir(sourcefile,fulldir,output_dir) |
|
219 |
|
220 if output_file: |
|
221 #Renaming output if defined |
|
222 targetfile = targetfile.replace(os.path.basename(targetfile), output_file) |
|
223 |
|
224 if sourcefile and targetfile: |
|
225 copylist.append((sourcefile,targetfile, external)) |
|
226 return copylist |
|
227 |
|
228 class ContentImplReaderBase(object): |
|
229 FILE_EXTENSIONS = ['content', 'contentml'] |
|
230 |
|
231 @classmethod |
|
232 def read_impl(cls, resource_ref, configuration, etree): |
|
233 parser = cls.parser_class() |
|
234 |
|
235 desc = parser.parse_desc(etree) |
|
236 outputs = parser.parse_outputs(etree) |
|
237 phase = parser.parse_phase(etree) |
|
238 tags = parser.parse_tags(etree) |
|
239 |
|
240 impl = ContentImpl(resource_ref, configuration) |
|
241 impl.desc = desc |
|
242 impl.outputs = outputs |
|
243 if tags: |
|
244 impl.set_tags(tags) |
|
245 for output in impl.outputs: |
|
246 output.set_configuration(configuration) |
|
247 if phase != None: |
|
248 impl.set_invocation_phase(phase) |
|
249 |
|
250 return impl |
|
251 |
|
252 class ContentImplReader1(ContentImplReaderBase, plugin.ReaderBase): |
|
253 NAMESPACE = 'http://www.s60.com/xml/content/1' |
|
254 parser_class = contentmlparser.Content1Parser |
|
255 |
|
256 class ContentImplReader2(ContentImplReaderBase, plugin.ReaderBase): |
|
257 NAMESPACE = 'http://www.s60.com/xml/content/2' |
|
258 parser_class = contentmlparser.Content2Parser |