মাভেন-শেড-প্লাগইন কীসের জন্য ব্যবহৃত হয় এবং আপনি কেন জাভা প্যাকেজগুলি স্থানান্তর করতে চান?


281

আমি খুঁজে পেয়েছি যে মাভেন-শেড-প্লাগইন কারও pom.xML এ ব্যবহৃত হচ্ছে। আমি এর আগে কখনও মাভেন-শেড-প্লাগইন ব্যবহার করি নি (এবং আমি একজন মেভেন এন 100 বি) তাই এটি ব্যবহার করার কারণ এবং এটি কী করে তা বোঝার চেষ্টা করেছি।

আমি মাভেন ডক্সের দিকে চেয়েছিলাম , তবে আমি এই বিবৃতিটি বুঝতে পারি না:

"এই প্লাগইনটি তার নির্ভরতা সহ একটি উবার-জারে শৈল্পিক প্যাকেজ করার সক্ষমতা সরবরাহ করে এবং নাম - নামকরণ - কিছু নির্ভরশীলতার প্যাকেজগুলিকে ছায়া দেয় provides"

পৃষ্ঠায় ডকুমেন্টেশন খুব নবাগত বান্ধব বলে মনে হচ্ছে না।

"উবার জার" কী? কেউ কেন একটি বানাতে চাইবে? নির্ভরতাগুলির প্যাকেজগুলির নামকরণের কী লাভ? আমি "উবার জারের জন্য বিষয়বস্তু নির্বাচন করা" এর মতো মাভেন-শেড-প্লাগইন অ্যাপাচি পৃষ্ঠায় উদাহরণগুলি দেখার চেষ্টা করেছি তবে "শেডিং" দিয়ে কী সম্পাদিত হচ্ছে তা আমি এখনও বুঝতে পারি না।

উদাহরণস্বরূপ উদাহরণ / ব্যবহারের ক্ষেত্রে কোনও পয়েন্টার (কেন এই ক্ষেত্রে শেডিংয়ের প্রয়োজন ছিল - এটি কী সমস্যা সমাধান করছে তা ব্যাখ্যা করে) প্রশংসা হবে would শেষ অবধি, আমি কখন মেভেন শেড-প্লাগইন ব্যবহার করব?


16
"উবার জার" নামকরণের জন্য আমার জার্মানদের সাথে একমাত্র সম্পর্ক রয়েছে, যেখানে "über" অর্থ "শেষ"। একসাথে আক্ষরিক অর্থে এর অর্থ "জার-ওভার-অল-অন্যান্য-জারস"। "শেডিং" "প্যাকেজ পুনঃনির্ধারণ" সমান যা সংঘর্ষে ক্লাস বা সংস্থানগুলির জন্য প্রয়োজন।
dma_k

1
s/reallocation/relocation/উপরের মন্তব্য।
ক্রিস্টোফার শুল্টজ

12
উবারের পাত্রটি কেবল একটি আংটির মতো: একটি জার তাদের সমস্তকে শাসন করার জন্য, একটি জার তাদের খুঁজে বের করার জন্য, একটি জার তাদের সমস্ত আনার জন্য এবং অন্ধকারে তাদের আবদ্ধ করে রাখে।
মারটি নিতো

উত্তর:


342

সংক্ষেপে উবার জেআর হ'ল একটি জেআর যা সমস্ত কিছু রয়েছে।

সাধারণত মাভেনে আমরা নির্ভরতা পরিচালনার উপর নির্ভর করি। একটি নিদর্শনটিতে কেবল নিজের ক্লাস / সংস্থান থাকে। প্রকল্পটি কখন নির্মিত হবে তার উপর নির্ভর করে প্রকল্পটি সমস্ত শিল্পকর্মগুলি (জেআর ইত্যাদি) সন্ধান করার জন্য মাভেন দায়বদ্ধ হবে।

একটি উবার-জার এমন একটি জিনিস যা সমস্ত নির্ভরতা গ্রহণ করে এবং নির্ভরতার বিষয়বস্তু আহরণ করে এবং প্রকল্পের শ্রেণি / সংস্থানগুলির সাথে এটি একটি বড় জেআর-তে রাখে। এ জাতীয় উবার-জারের দ্বারা, কার্যকর করা সহজ, কারণ আপনার অ্যাপ্লিকেশনটি চালানোর জন্য আপনার কয়েক টন ছোট জারের পরিবর্তে কেবলমাত্র একটি বড় জেআর প্রয়োজন। এটি কিছু ক্ষেত্রে বিতরণও সহজ করে দেয়।

শুধু একটি পার্শ্ব নোট। মাবার নির্ভরতা হিসাবে উবার-জার ব্যবহার করা এড়িয়ে চলুন, কারণ এটি মাভেনের নির্ভরতা রেজোলিউশন বৈশিষ্ট্যটিকে নষ্ট করছে। সাধারণত আমরা কেবলমাত্র প্রকৃত স্থাপনার জন্য বা ম্যানুয়াল বিতরণের জন্য চূড়ান্ত নিদর্শনগুলির জন্য উবার-জার তৈরি করি, তবে মাভেনের সংগ্রহস্থলের জন্য রাখি না।


আপডেট: আমি সবেমাত্র আবিষ্কার করেছি যে আমি প্রশ্নের একটি অংশের উত্তর দেইনি: "নির্ভরতাগুলির প্যাকেজগুলির নাম পরিবর্তন করার কী আছে?" এখানে কিছু সংক্ষিপ্ত আপডেট দেওয়া হয়েছে এবং আশা করা যায় যে একই ধরণের প্রশ্ন থাকা লোকদের সহায়তা করবে।

স্থাপনার স্বাচ্ছন্দ্যের জন্য উবার-জার তৈরি করা শেড প্লাগইনের এক ব্যবহৃত ক্ষেত্রে। অন্যান্য সাধারণ ব্যবহারের ক্ষেত্রেও রয়েছে যা প্যাকেজের নাম পরিবর্তন করে involve

উদাহরণস্বরূপ, আমি Fooলাইব্রেরিটি বিকাশ করছি , যা গ্রন্থাগারের নির্দিষ্ট সংস্করণে (উদাহরণস্বরূপ 1.0) নির্ভর করে Bar। ধরে নিচ্ছি আমি লাইবের অন্যান্য সংস্করণ ব্যবহার করতে পারি না Bar(কারণ এপিআই পরিবর্তন, বা অন্যান্য প্রযুক্তিগত সমস্যা ইত্যাদি)। যদি আমি কেবল মাভেনের নির্ভরতা Bar:1.0হিসাবে ঘোষণা Fooকরি তবে কোনও সমস্যার মধ্যে পড়ে যাওয়ার সম্ভাবনা রয়েছে: একটি Quxপ্রকল্প নির্ভর করে Foo, এবং এটিও Bar:2.0(এবং এটি ব্যবহার করতে পারে না Bar:1.0কারণ এতে Quxনতুন বৈশিষ্ট্যটি ব্যবহার করা দরকার Bar:2.0)। এই দ্বিধাটি এখানে: Quxব্যবহার করা উচিত Bar:1.0( Quxকোনটির কোড কাজ করবে না) বা Bar:2.0(কোন Fooকোডটি কাজ করবে না)?

এই সমস্যাটি সমাধান করার জন্য, এর বিকাশকারী এর Fooব্যবহারের পুনর্নবীকরণের জন্য শেড প্লাগইন ব্যবহার করতে বেছে নিতে পারেন Bar, যাতে Bar:1.0জারে সমস্ত ক্লাস জারে এমবেড করা থাকে এবং Fooএমবেডেড Barশ্রেণীর প্যাকেজটি থেকে পরিবর্তিত com.barহয় com.foo.bar। এটি করে, Quxনিরাপদে নির্ভর করতে পারে Bar:2.0কারণ এখন Fooআর নির্ভর করে না Bar, এবং এটি Barঅন্য প্যাকেজে অবস্থিত "পরিবর্তিত" এর নিজস্ব অনুলিপিটি ব্যবহার করছে ।


5
ধন্যবাদ, যে অনেক সাহায্য করে। এটি "শেডিং" বলে কারণ এটি উবার-জারের অভ্যন্তরের নির্ভরতা এবং অন্যান্য জারগুলি গোপন করে?
nonbeing

6
নামের পেছনের কারণ সম্পর্কে আমি সত্যিই নিশ্চিত নই, তবে এর প্রথম পৃষ্ঠা থেকে মনে হয় "শেডিং" নির্ভরতার "গোপনীয়তা" বর্ণনা করছে। আপনি allyচ্ছিকভাবে শেডযুক্ত জেআর-তে কিছু নির্ভরতা অন্তর্ভুক্ত করতে পারেন, শেড প্লাগইন আপনার জন্য একটি সঠিক পিওএম তৈরি করবে যা অন্তর্ভুক্ত নির্ভরতাগুলি সরিয়ে দেয়। দেখে মনে হচ্ছে শেডিং এই প্রক্রিয়াটি বর্ণনা করছে
অ্যাড্রিয়ান শাম

1
@ অ্যাড্রিয়ানশাম: আপনি কীভাবে ছায়ার প্লাগইন ব্যবহার না করে একটি উবার জার তৈরি করবেন তা পরামর্শ দিতে পারেন? বা বিশেষত কীভাবে "মাভেনের নির্ভরতা সমাধান বৈশিষ্ট্যটি নষ্ট করা" সমাধান করবেন?
সুরজ মেনন

3
@ সুরজমেনন: শেড প্লাগইন ব্যবহার করা উবার-জার তৈরির সহজতম উপায়। তবে আপনি অ্যাসেম্বলি প্লাগইনও ব্যবহার করতে পারবেন এবং বিল্ট-ইন jar-with-dependencyডিসক্রিপটরটি ব্যবহার করতে পারেন । উবার-জার ব্যবহার করে নির্ভরতা রসলের সমস্যার জন্য, আমি ইতিমধ্যে আমার উত্তরে উল্লেখ করেছি: উবার-জারকে নির্ভরতা, সময়কাল হিসাবে ব্যবহার করবেন না। আরও কিছু বিশদে বিশদ: আপনি উবার-জার তৈরি করার আগে আপনার স্বাভাবিক নির্ভরতা সহ একটি সাধারণ প্রকল্প করা উচিত। সেই আসল নিদর্শনটি হ'ল আপনার নির্ভরতা হিসাবে ব্যবহার করা উচিত (উবার-জারের পরিবর্তে)
অ্যাড্রিয়ান শাম

1
কেবল একটি ছোট্ট প্রশ্ন: এটি Class.forNameকাজ করা বন্ধ করে দেয়?
সফট

64

আমি সম্প্রতি নিজেকে ভাবছিলাম যে স্থিতিস্থাপক অনুসন্ধানটি কেন শেড করে এবং এর কয়েকটি নির্ভরতাগুলির কয়েকটি (তবে সমস্ত নয়) সরিয়ে দেয়। প্রকল্পের রক্ষণাবেক্ষণকারীর কাছ থেকে এখানে একটি ব্যাখ্যা দেওয়া হয়েছে, @ কিমচি :

শেডিং অংশটি ইচ্ছাকৃত, ছায়াময় গ্রন্থাগারগুলি যা আমরা ইলাস্টিকসर्चে ব্যবহার করি তা ইলাস্টিকের অনুসন্ধানের সমস্ত উদ্দেশ্য এবং উদ্দেশ্য অংশের জন্য হয়, ব্যবহৃত সংস্করণটি কীভাবে ইলাস্টিকসার্কটি প্রকাশ করে এবং কীভাবে এটি গ্রন্থাগারটি কাজ করে তার অভ্যন্তরের উপর ভিত্তি করে গ্রন্থাগারটি কীভাবে ব্যবহার করে (এবং সংস্করণগুলির মধ্যে পরিবর্তন হয়), নেট এবং পেয়ারা দুর্দান্ত উদাহরণ।

বিটিডব্লিউ, আমি ইলাস্টিকের বেশ কয়েকটি জার সরবরাহ করতে আসলেই কোনও সমস্যা নেই, একটি লুসিনের ছায়াযুক্ত নয় এবং একটি লুসিন শেডযুক্ত। যদিও maven দিয়ে এটি করবেন তা নিশ্চিত নয়। আমি এমন কোনও সংস্করণ সরবরাহ করতে চাই না যা উদাহরণস্বরূপ নেট / জ্যাকসনকে ছায়া দেয় না, কারণ তাদের কাছে গভীর ভীতি ব্যবহারের স্থিতিস্থাপক ব্যবহার রয়েছে (উদাহরণস্বরূপ, বর্তমানের ব্যতীত নেটটির আগের কোনও সংস্করণ সহ আসন্ন বাফারিং উন্নতি ব্যবহার করে) বাস্তবে যথেষ্ট কম ব্যবহারের তুলনায় বেশি মেমরি ব্যবহার করুন)।

- https://github.com/elasticsearch/elasticsearch/issues/2091#issuecomment-7156766

এবং আরেকজন এখানে ড্রয়ার থেকে :

শেডিংটি আমাদের কোডের কাছে আমাদের নির্ভরতা (বিশেষত নেট, লুসিন, পেয়ারা) কাছে রাখা জরুরী যাতে প্রবাহ সরবরাহকারী পিছিয়ে থাকলেও আমরা কোনও সমস্যা সমাধান করতে পারি। এটি সম্ভব হয় আমরা কোডের সংশোধিত সংস্করণগুলি বিতরণ করব, যা আপনার নির্দিষ্ট ইস্যুতে সহায়তা করবে (উদাহরণস্বরূপ # 2091), তবে আমরা এই মুহুর্তে ছায়াযুক্ত নির্ভরতাগুলি সরাতে পারি না। আরও ভাল সমাধান না হওয়া পর্যন্ত আপনি আপনার উদ্দেশ্যে ES এর স্থানীয় সংস্করণ তৈরি করতে পারেন।

- https://github.com/elasticsearch/elasticsearch/pull/3244#issuecomment-20125452

সুতরাং, এটি এক ব্যবহারের কেস। উদাহরণস্বরূপ উদাহরণ হিসাবে, নীচে ইলাস্টিকসার্কের pom.xML (v0.90.5) তে ম্যাভেন-শেড-প্লাগইন কীভাবে ব্যবহৃত হয় তা নীচে দেওয়া হয়েছে। artifactSet::includeলাইন এটা নির্দেশ কি পণ্য JAR- র (মূলত, তারা আনজিপ করা হয় এবং এবং elasticsearch নিজস্ব শ্রেণীর পাশাপাশি পুনরায় প্যাকেজ যখন লক্ষ্য elasticsearch বয়াম উত্পাদিত হয়। (যদি আপনি ইতিমধ্যে জানেন না বা টান নির্ভরতা, এক বয়াম ফাইল প্রোগ্রামের ক্লাস, রিসোর্স ইত্যাদিসহ একটি জিপ ফাইল এবং কিছু মেটাডেটা it's এটি কীভাবে একসাথে রাখা হয়েছে তা দেখতে আপনি একটি নিষ্কাশন করতে পারেন))

relocations::relocationএই ক্ষেত্রে তাদের অধীনে আনয়ন - লাইন ছাড়া প্রতিটি ক্ষেত্রে তারা নির্দিষ্ট বদল নির্ভরতা এর ক্লাস প্রযোজ্য হলেও, একই রকম org.elasticsearch.common

পরিশেষে filtersবিভাগটি লক্ষ্য জেআর থেকে কিছু স্টাফ বাদ দেয় যা সেখানে হওয়া উচিত নয় - যেমন জেআর মেটাডেটা, পিপড়া বিল্ড ফাইল, টেক্সট ফাইল ইত্যাদি some

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.1</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <minimizeJar>true</minimizeJar>
            <artifactSet>
                <includes>
                    <include>com.google.guava:guava</include>
                    <include>net.sf.trove4j:trove4j</include>
                    <include>org.mvel:mvel2</include>
                    <include>com.fasterxml.jackson.core:jackson-core</include>
                    <include>com.fasterxml.jackson.dataformat:jackson-dataformat-smile</include>
                    <include>com.fasterxml.jackson.dataformat:jackson-dataformat-yaml</include>
                    <include>joda-time:joda-time</include>
                    <include>io.netty:netty</include>
                    <include>com.ning:compress-lzf</include>
                </includes>
            </artifactSet>
            <relocations>
                <relocation>
                    <pattern>com.google.common</pattern>
                    <shadedPattern>org.elasticsearch.common</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>gnu.trove</pattern>
                    <shadedPattern>org.elasticsearch.common.trove</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>jsr166y</pattern>
                    <shadedPattern>org.elasticsearch.common.util.concurrent.jsr166y</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>jsr166e</pattern>
                    <shadedPattern>org.elasticsearch.common.util.concurrent.jsr166e</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.mvel2</pattern>
                    <shadedPattern>org.elasticsearch.common.mvel2</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>com.fasterxml.jackson</pattern>
                    <shadedPattern>org.elasticsearch.common.jackson</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.joda</pattern>
                    <shadedPattern>org.elasticsearch.common.joda</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.jboss.netty</pattern>
                    <shadedPattern>org.elasticsearch.common.netty</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>com.ning.compress</pattern>
                    <shadedPattern>org.elasticsearch.common.compress</shadedPattern>
                </relocation>
            </relocations>
            <filters>
                <filter>
                    <artifact>*:*</artifact>
                    <excludes>
                        <exclude>META-INF/license/**</exclude>
                        <exclude>META-INF/*</exclude>
                        <exclude>META-INF/maven/**</exclude>
                        <exclude>LICENSE</exclude>
                        <exclude>NOTICE</exclude>
                        <exclude>/*.txt</exclude>
                        <exclude>build.properties</exclude>
                    </excludes>
                </filter>
            </filters>
        </configuration>
    </plugin>
</plugins>

2

ছোট সতর্কতা

যদিও কেউ বর্ণিত নয় যে কেন কেউ মাভেন-শেড-প্লাগইন ব্যবহার করতে চান (যেহেতু নির্বাচিত উত্তরটি এটি বেশ ভালভাবে বর্ণনা করে) তবে আমি লক্ষ করতে চাই যে এতে আমার সমস্যা ছিল। এটি জারকে পরিবর্তন করেছে (যেহেতু এটি করছে তা) এবং এটি আমার সফ্টওয়্যারটিতে রিগ্রেশন সৃষ্টি করে।

সুতরাং, এটি (বা ম্যাভেন-জারজার-প্লাগইন) ব্যবহার না করে আমি জারজারের বাইনারি ব্যবহার করেছি যা মনে হয় কোনও সমস্যা ছাড়াই কাজ করে।

আমি এখানে আমার সমাধান পোস্ট করছি কারণ একটি শালীন সমাধান খুঁজে পেতে আমাকে কিছুটা সময় লেগেছে।


ডাউনলাড জারজারের জেআর ফাইল

আপনি এখান থেকে জারটি ডাউনলোড করতে পারেন: https://code.google.com/p/jarjar/ বাম মেনুতে আপনি এটি ডাউনলোড করার জন্য একটি লিঙ্ক পেয়েছেন।


একটি জেআর এর ক্লাসগুলি একটি প্যাকেজ থেকে অন্য প্যাকেজে স্থানান্তর করতে জারজারকে কীভাবে ব্যবহার করবেন

এই উদাহরণে আমরা প্যাকেজটি "com.fasterxML.jackson" থেকে "io.kuku.d dependency.com.fasterxml.jackson" তে পরিবর্তন করব। - উত্স জেআরকে "জ্যাকসন-ডাটাবাইন্ড-২..4.৪.জার" এবং নতুন সংশোধিত (টার্গেট) জেআরকে "কুকু-জ্যাকসন-ডাটাবাইন্ড-২. new.৪.জার" বলা হয়। - "জারজার" জেআর ফাইলটি 1.4 সংস্করণে রয়েছে

  1. একটি "নিয়ম। টেক্সট" ফাইল তৈরি করুন। ফাইলের বিষয়বস্তু হওয়া উচিত ('@' চরিত্রের আগে সময়কাল দেখুন): নিয়ম com.fasterxML.jackson। ** io.kuku.d dependency.com.fasterxml.jackson। @ 1

  2. নিম্নলিখিত কমান্ডটি চালান: জাভা-জারজার -১.৪.জার প্রক্রিয়া নিয়ম t টেক্সট জ্যাকসন-ডাটাবাইন্ড -২.6.৪.জার কুকু-জ্যাকসন-ডাটাবিন্দ -২.6.৪.জার


স্থানীয় সংগ্রহস্থলে পরিবর্তিত জেআর ইনস্টল করা

এই ক্ষেত্রে আমি "সি: \ মাই-জারস \" ফোল্ডারে থাকা 3 টি ফাইল ইনস্টল করছি।

এমভিএন ইনস্টল: ইনস্টল-ফাইল -ডফিল = সি: \ আমার-জারস \ কুকু-জ্যাকসন-টিকা -২. 2..৪.জার -ডগ্রুপআইডি = আইও.কুকু.ডেপেনডেস-ডার্টিফ্যাক্টআইডি = কুকু-জ্যাকসন-টিকা-পরিবর্তন = ২.6.৪ - Dpackaging = বয়াম

এমভিএন ইনস্টল: ইনস্টল-ফাইল -ডফিল = সি: \ মাই-জারস \ কুকু-জ্যাকসন-কোর-২..4.৪.জার -ডগ্রুপআইডি = আইও.কুকু.ডেপেনডেস-ডার্টিফ্যাক্ট আইডি = কুকু-জ্যাকসন-কোর-ডারভিশন = ২.6.৪ - Dpackaging = বয়াম

এমভিএন ইনস্টল: ইনস্টল-ফাইল -ডফিল = সি: \ মাই-জারস \ কুকু-জ্যাকসন-ডাটাবাইন্ড -২.6.৪.জার -ডগ্রুপআইডি = আইও.কুকু.ডেপেন্ডেস-ডার্টিফ্যাক্ট আইডি = কুকু-জ্যাকসন-টিকা-পরিবর্তন = ২.6.৪ - Dpackaging = বয়াম


প্রকল্পের পমের পরিবর্তিত জেআরগুলি ব্যবহার করে

এই উদাহরণস্বরূপ, প্রকল্পগুলিতে এটি "নির্ভরতা" উপাদান:

<dependencies>
    <!-- ================================================== -->
    <!-- kuku JARs -->
    <!-- ================================================== -->
    <dependency>
        <groupId>io.kuku.dependencies</groupId>
        <artifactId>kuku-jackson-annotations</artifactId>
        <version>2.6.4</version>
    </dependency>
    <dependency>
        <groupId>io.kuku.dependencies</groupId>
        <artifactId>kuku-jackson-core</artifactId>
        <version>2.6.4</version>
    </dependency>
    <dependency>
        <groupId>io.kuku.dependencies</groupId>
        <artifactId>kuku-jackson-databind</artifactId>
        <version>2.6.4</version>
    </dependency>
</dependencies>

1
এই বিকল্প পরামর্শের জন্য আপনাকে ধন্যবাদ। এটি আমি যা খুঁজছিলাম তা নয় তবে উত্তরাধিকার লাইব্রেরিগুলিতে 1-বার প্যাকেজ অনুবাদ প্রয়োগ করার জন্য এটি একটি সহজ এবং দ্রুত সমাধান হিসাবে দেখা গেছে যা কখনই পরিবর্তন হবে না।
ফ্রিলিং

আপনি কি তাদের নিজ নিজ আউটপুটটির সামগ্রীর তুলনা করে এ জাতীয় ব্যর্থতার কারণটি খুঁজে পেয়েছেন?
Tribbloid

2

আমি মনে করি "ছায়াময়" জারের প্রয়োজনীয়তার একটি উদাহরণ একটি ডাব্লুএস ল্যাম্বদা ফাংশন। তারা আপনাকে কেবল 1 জার আপলোড করতে দেবে বলে মনে হচ্ছে, আপনার মতো জারগুলির একটি সম্পূর্ণ সংগ্রহটি আপনার পছন্দ মতো .war ফাইলটিতে খুঁজে পাবে। সুতরাং, প্রকল্পের সমস্ত নির্ভরতাগুলির সাথে একটি একক .ar তৈরি করা আপনাকে এটি করতে দেয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.