1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "precompiled_ucb.hxx"
25 
26 #include "ucpext_provider.hxx"
27 #include "ucpext_content.hxx"
28 
29 /** === begin UNO includes === **/
30 /** === end UNO includes === **/
31 
32 #include <ucbhelper/contentidentifier.hxx>
33 #include <osl/diagnose.h>
34 #include <osl/mutex.hxx>
35 #include <comphelper/componentcontext.hxx>
36 #include <rtl/ustrbuf.hxx>
37 
38 //......................................................................................................................
39 namespace ucb { namespace ucp { namespace ext
40 {
41 //......................................................................................................................
42 
43 	/** === begin UNO using === **/
44 	using ::com::sun::star::uno::Reference;
45 	using ::com::sun::star::uno::XInterface;
46 	using ::com::sun::star::uno::UNO_QUERY;
47 	using ::com::sun::star::uno::UNO_QUERY_THROW;
48 	using ::com::sun::star::uno::UNO_SET_THROW;
49 	using ::com::sun::star::uno::Exception;
50 	using ::com::sun::star::uno::RuntimeException;
51 	using ::com::sun::star::uno::Any;
52 	using ::com::sun::star::uno::makeAny;
53 	using ::com::sun::star::uno::Sequence;
54 	using ::com::sun::star::uno::Type;
55     using ::com::sun::star::lang::XMultiServiceFactory;
56     using ::com::sun::star::ucb::XContentIdentifier;
57     using ::com::sun::star::ucb::IllegalIdentifierException;
58     using ::com::sun::star::ucb::XContent;
59     using ::com::sun::star::uno::XComponentContext;
60 	/** === end UNO using === **/
61 
62     //==================================================================================================================
63     //= ContentProvider
64     //==================================================================================================================
65     //------------------------------------------------------------------------------------------------------------------
66     ContentProvider::ContentProvider( const Reference< XMultiServiceFactory >& i_rServiceManager )
67         :ContentProvider_Base( i_rServiceManager )
68     {
69     }
70 
71     //------------------------------------------------------------------------------------------------------------------
72     ContentProvider::~ContentProvider()
73     {
74     }
75 
76     //------------------------------------------------------------------------------------------------------------------
77     ::rtl::OUString SAL_CALL ContentProvider::getImplementationName_static() throw (RuntimeException)
78     {
79         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.ucp.ext.ContentProvider" ) );
80     }
81 
82     //------------------------------------------------------------------------------------------------------------------
83     ::rtl::OUString SAL_CALL ContentProvider::getImplementationName() throw (RuntimeException)
84     {
85         return getImplementationName_static();
86     }
87 
88     //------------------------------------------------------------------------------------------------------------------
89     Sequence< ::rtl::OUString > SAL_CALL ContentProvider::getSupportedServiceNames_static(  ) throw (RuntimeException)
90     {
91         Sequence< ::rtl::OUString > aServiceNames(2);
92         aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.ContentProvider" ) );
93         aServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.ExtensionContentProvider" ) );
94         return aServiceNames;
95     }
96 
97     //------------------------------------------------------------------------------------------------------------------
98     Sequence< ::rtl::OUString > SAL_CALL ContentProvider::getSupportedServiceNames(  ) throw (RuntimeException)
99     {
100         return getSupportedServiceNames_static();
101     }
102 
103     //------------------------------------------------------------------------------------------------------------------
104     Reference< XInterface > ContentProvider::Create( const Reference< XComponentContext >& i_rContext )
105     {
106         const ::comphelper::ComponentContext aContext( i_rContext );
107         return *( new ContentProvider( aContext.getLegacyServiceFactory() ) );
108     }
109 
110     //------------------------------------------------------------------------------------------------------------------
111     ::rtl::OUString ContentProvider::getRootURL()
112     {
113         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.extension://" ) );
114     }
115 
116     //------------------------------------------------------------------------------------------------------------------
117     ::rtl::OUString ContentProvider::getArtificialNodeContentType()
118     {
119         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.extension-content" ) );
120     }
121 
122     //------------------------------------------------------------------------------------------------------------------
123     namespace
124     {
125         void lcl_ensureAndTransfer( ::rtl::OUString& io_rIdentifierFragment, ::rtl::OUStringBuffer& o_rNormalization, const sal_Unicode i_nLeadingChar )
126         {
127             if ( ( io_rIdentifierFragment.getLength() == 0 ) || ( io_rIdentifierFragment[0] != i_nLeadingChar ) )
128                 throw IllegalIdentifierException();
129             io_rIdentifierFragment = io_rIdentifierFragment.copy( 1 );
130             o_rNormalization.append( i_nLeadingChar );
131         }
132     }
133 
134     //------------------------------------------------------------------------------------------------------------------
135     Reference< XContent > SAL_CALL ContentProvider::queryContent( const Reference< XContentIdentifier  >& i_rIdentifier )
136         throw( IllegalIdentifierException, RuntimeException )
137     {
138         // Check URL scheme...
139         const ::rtl::OUString sScheme( rtl::OUString::createFromAscii( "vnd.sun.star.extension" ) );
140         if ( !i_rIdentifier->getContentProviderScheme().equalsIgnoreAsciiCase( sScheme ) )
141             throw IllegalIdentifierException();
142 
143         // normalize the identifier
144         const ::rtl::OUString sIdentifier( i_rIdentifier->getContentIdentifier() );
145 
146         // the scheme needs to be lower-case
147         ::rtl::OUStringBuffer aComposer;
148         aComposer.append( sIdentifier.copy( 0, sScheme.getLength() ).toAsciiLowerCase() );
149 
150         // one : is required after the scheme
151         ::rtl::OUString sRemaining( sIdentifier.copy( sScheme.getLength() ) );
152         lcl_ensureAndTransfer( sRemaining, aComposer, ':' );
153 
154         // and at least one /
155         lcl_ensureAndTransfer( sRemaining, aComposer, '/' );
156 
157         // the normalized form requires one additional /, but we also accept identifiers which don't have it
158         if ( sRemaining.getLength() == 0 )
159         {
160             // the root content is a special case, it requires ///
161             aComposer.appendAscii( "//" );
162         }
163         else
164         {
165             if ( sRemaining[0] != '/' )
166             {
167                 aComposer.append( sal_Unicode( '/' ) );
168                 aComposer.append( sRemaining );
169             }
170             else
171             {
172                 lcl_ensureAndTransfer( sRemaining, aComposer, '/' );
173                 // by now, we moved "vnd.sun.star.extension://" from the URL to aComposer
174                 if ( sRemaining.getLength() == 0 )
175                 {
176                     // again, it's the root content, but one / is missing
177                     aComposer.append( sal_Unicode( '/' ) );
178                 }
179                 else
180                 {
181                     aComposer.append( sRemaining );
182                 }
183             }
184         }
185         const Reference< XContentIdentifier > xNormalizedIdentifier( new ::ucbhelper::ContentIdentifier( m_xSMgr, aComposer.makeStringAndClear() ) );
186 
187         ::osl::MutexGuard aGuard( m_aMutex );
188 
189         // check if a content with given id already exists...
190         Reference< XContent > xContent( queryExistingContent( xNormalizedIdentifier ).get() );
191         if ( xContent.is() )
192             return xContent;
193 
194         // create a new content
195         xContent = new Content( m_xSMgr, this, xNormalizedIdentifier );
196         if ( !xContent->getIdentifier().is() )
197             throw IllegalIdentifierException();
198 
199         registerNewContent( xContent );
200         return xContent;
201     }
202 
203 //......................................................................................................................
204 } } }   // namespace ucb::ucp::ext
205 //......................................................................................................................
206