1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "stdafx.h"
17 
18 #include <zorba/transcode_stream.h>
19 
20 #include "diagnostics/assert.h"
21 #include "diagnostics/xquery_diagnostics.h"
22 
23 #include "runtime/fetch/fetch.h"
24 #include "system/globalenv.h"
25 #include "store/api/item_factory.h"
26 
27 #include "context/static_context.h"
28 #include "context/uri_resolver.h"
29 
30 
31 namespace zorba {
32 
33 /*******************************************************************************
34 ********************************************************************************/
35 std::auto_ptr<internal::StreamResource>
getFetchResource(const store::Item_t & aUri,const store::Item_t & aKind,const static_context * aSctx,const QueryLoc & aLoc)36 getFetchResource(
37     const store::Item_t& aUri,
38     const store::Item_t& aKind,
39     const static_context* aSctx,
40     const QueryLoc& aLoc)
41 {
42   internal::EntityData::Kind lKind;
43   zstring lKindStr = aKind->getStringValue();
44 
45   // Figure out the EntityKind (any better way to do this?)
46   if ( ! lKindStr.compare("SOME_CONTENT")) {
47     lKind = internal::EntityData::SOME_CONTENT;
48   }
49   else if ( ! lKindStr.compare("SCHEMA")) {
50     lKind = internal::EntityData::SCHEMA;
51   }
52   else if ( ! lKindStr.compare("MODULE")) {
53     lKind = internal::EntityData::MODULE;
54   }
55 #ifndef ZORBA_NO_FULL_TEXT
56   else if ( ! lKindStr.compare("THESAURUS")) {
57     lKind = internal::EntityData::THESAURUS;
58   }
59   else if ( ! lKindStr.compare("STOP_WORDS")) {
60     lKind = internal::EntityData::STOP_WORDS;
61   }
62 #endif /* ZORBA_NO_FULL_TEXT */
63   else {
64     throw XQUERY_EXCEPTION(
65           zerr::ZXQP0026_INVALID_ENUM_VALUE,
66           ERROR_PARAMS(lKindStr, "entityKind"),
67           ERROR_LOC(aLoc));
68   }
69 
70   try {
71     // ask the uri mappers and resolvers to give
72     // me a resource of specified kind
73     zstring lErrorMessage;
74 
75     std::auto_ptr<internal::Resource> lRes = aSctx->resolve_uri(
76       aUri->getStringValue(),
77       lKind,
78       lErrorMessage);
79 
80     std::auto_ptr<internal::StreamResource> lStreamRes(
81       dynamic_cast<internal::StreamResource*>(lRes.get()));
82 
83     if ( !lStreamRes.get() )
84     {
85       throw XQUERY_EXCEPTION(
86         zerr::ZXQP0025_COULD_NOT_FETCH_RESOURCE,
87         ERROR_PARAMS(
88           aUri->getStringValue(),
89           ZED(ZXQP0025_RESOURCE_NOT_FOUND)
90         ),
91         ERROR_LOC( aLoc )
92       );
93     }
94 
95     lRes.release();
96 
97     return lStreamRes;
98 
99   } catch (ZorbaException const& e) {
100     throw XQUERY_EXCEPTION(
101       zerr::ZXQP0025_COULD_NOT_FETCH_RESOURCE,
102       ERROR_PARAMS( aUri->getStringValue(), e.what() ),
103       ERROR_LOC( aLoc )
104     );
105   }
106 }
107 
108 /*******************************************************************************
109 ********************************************************************************/
110 void
destroyStream(std::istream & aStream)111 FetchContentIterator::destroyStream(std::istream& aStream)
112 {
113   delete &aStream;
114 }
115 
116 bool
nextImpl(store::Item_t & result,PlanState & aPlanState) const117 FetchContentIterator::nextImpl(
118     store::Item_t& result,
119     PlanState& aPlanState) const
120 {
121   store::Item_t lUri;
122   store::Item_t lEntityKind;
123   store::Item_t lEncoding;
124   zstring lEncodingStr;
125   std::auto_ptr<internal::StreamResource> lRes;
126 
127   PlanIteratorState* state;
128   DEFAULT_STACK_INIT(PlanIteratorState, state, aPlanState);
129 
130   consumeNext(lUri, theChildren[0].getp(), aPlanState);
131   consumeNext(lEntityKind, theChildren[1].getp(), aPlanState);
132   consumeNext(lEncoding, theChildren[2].getp(), aPlanState);
133 
134   lEncodingStr = lEncoding->getStringValue();
135 
136   lRes = getFetchResource(lUri, lEntityKind, theSctx, loc);
137 
138   if (transcode::is_necessary(lEncodingStr.c_str()))
139   {
140     if (!transcode::is_supported(lEncodingStr.c_str()))
141     {
142       throw XQUERY_EXCEPTION(
143           zerr::ZXQP0006_UNKNOWN_ENCODING,
144           ERROR_PARAMS( lEncodingStr.c_str() ),
145           ERROR_LOC( loc )
146         );
147     }
148     transcode::attach(*lRes->getStream(), lEncodingStr.c_str());
149   }
150 
151   // return the resource in a streamable string. This transfers memory
152   // ownership of the istream (via its StreamReleaser) to the StreamableString
153   // object, so we then remove the StreamReleaser from the StreamResource.
154   GENV_ITEMFACTORY->createStreamableString(
155         result,
156         *lRes->getStream(),
157         lRes->getStreamReleaser(),
158         lRes->isStreamSeekable()
159   );
160   lRes->setStreamReleaser(nullptr);
161 
162   STACK_PUSH(result != NULL, state);
163 
164   STACK_END(state);
165 }
166 
167 
168 /*******************************************************************************
169 ********************************************************************************/
170 void
destroyStream(std::istream & aStream)171 FetchContentBinaryIterator::destroyStream(std::istream& aStream)
172 {
173   delete &aStream;
174 }
175 
176 bool
nextImpl(store::Item_t & result,PlanState & aPlanState) const177 FetchContentBinaryIterator::nextImpl(
178     store::Item_t& result,
179     PlanState& aPlanState) const
180 {
181   store::Item_t lUri;
182   store::Item_t lEntityKind;
183   std::auto_ptr<internal::StreamResource> lRes;
184 
185   PlanIteratorState* state;
186   DEFAULT_STACK_INIT(PlanIteratorState, state, aPlanState);
187 
188   consumeNext(lUri, theChildren[0].getp(), aPlanState);
189   consumeNext(lEntityKind, theChildren[1].getp(), aPlanState);
190 
191   lRes = getFetchResource(lUri, lEntityKind, theSctx, loc);
192 
193   // return the resource in a streamable base64. This transfers memory
194   // ownership of the istream (via its StreamReleaser) to the StreamableBase64BinaryItem
195   // object, so we then remove the StreamReleaser from the StreamResource.
196   GENV_ITEMFACTORY->createStreamableBase64Binary(
197         result,
198         *lRes->getStream(),
199         lRes->getStreamReleaser(),
200         lRes->isStreamSeekable(),
201         false
202   );
203   lRes->setStreamReleaser(nullptr);
204 
205   STACK_PUSH(result != NULL, state);
206 
207   STACK_END(state);
208 }
209 
210 
211 /*******************************************************************************
212 ********************************************************************************/
213 bool
nextImpl(store::Item_t & result,PlanState & aPlanState) const214 FetchContentTypeIterator::nextImpl(
215     store::Item_t& result,
216     PlanState& aPlanState) const
217 {
218   PlanIteratorState* state;
219   DEFAULT_STACK_INIT(PlanIteratorState, state, aPlanState);
220 
221   STACK_PUSH(false, state);
222 
223   STACK_END(state);
224 }
225 
226 } /* namespace zorba */
227 /* vim:set et sw=2 ts=2: */
228